home *** CD-ROM | disk | FTP | other *** search
/ Amiga Format CD 7 / Amiga Format AFCD07 (Dec 1996, Issue 91).iso / serious / shareware / comms / non-internet / samba / source / reply.c < prev    next >
C/C++ Source or Header  |  1996-06-26  |  80KB  |  3,221 lines

  1. /* 
  2.    Unix SMB/Netbios implementation.
  3.    Version 1.9.
  4.    Main SMB reply routines
  5.    Copyright (C) Andrew Tridgell 1992-1995
  6.    
  7.    This program is free software; you can redistribute it and/or modify
  8.    it under the terms of the GNU General Public License as published by
  9.    the Free Software Foundation; either version 2 of the License, or
  10.    (at your option) any later version.
  11.    
  12.    This program is distributed in the hope that it will be useful,
  13.    but WITHOUT ANY WARRANTY; without even the implied warranty of
  14.    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  15.    GNU General Public License for more details.
  16.    
  17.    You should have received a copy of the GNU General Public License
  18.    along with this program; if not, write to the Free Software
  19.    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  20. */
  21. /*
  22.    This file handles most of the reply_ calls that the server
  23.    makes to handle specific protocols
  24. */
  25.  
  26.  
  27. #include "includes.h"
  28. #include "loadparm.h"
  29. #include "trans2.h"
  30.  
  31. /* look in server.c for some explanation of these variables */
  32. extern int Protocol;
  33. extern int DEBUGLEVEL;
  34. extern int chain_size;
  35. extern int maxxmit;
  36. extern int chain_fnum;
  37. extern char magic_char;
  38. extern connection_struct Connections[];
  39. extern files_struct Files[];
  40. extern BOOL case_sensitive;
  41. extern pstring sesssetup_user;
  42. extern int Client;
  43.  
  44. /* this macro should always be used to extract an fnum (smb_fid) from
  45. a packet to ensure chaining works correctly */
  46. #define GETFNUM(buf,where) (chain_fnum!= -1?chain_fnum:SVAL(buf,where))
  47.  
  48.  
  49. /****************************************************************************
  50.   reply to an special message 
  51. ****************************************************************************/
  52. int reply_special(char *inbuf,char *outbuf)
  53. {
  54.   int outsize = 4;
  55.   int msg_type = CVAL(inbuf,0);
  56.   int msg_flags = CVAL(inbuf,1);
  57.   pstring name1,name2;
  58.   extern fstring remote_machine;
  59.   extern fstring local_machine;
  60.   char *p;
  61.  
  62.   *name1 = *name2 = 0;
  63.  
  64.   smb_setlen(outbuf,0);
  65.  
  66.   switch (msg_type)
  67.     {
  68.     case 0x81: /* session request */
  69.       CVAL(outbuf,0) = 0x82;
  70.       CVAL(outbuf,3) = 0;
  71.       if (name_len(inbuf+4) > 50)
  72.     {
  73.       DEBUG(0,("Invalid name length in session request\n"));
  74.       return(0);
  75.     }
  76.       name_extract(inbuf,4,name1);
  77.       name_extract(inbuf,4 + name_len(inbuf + 4),name2);
  78.       DEBUG(2,("netbios connect: name1=%s name2=%s\n",name1,name2));      
  79.  
  80.       strcpy(remote_machine,name2);
  81.       trim_string(remote_machine," "," ");
  82.       p = strchr(remote_machine,' ');
  83.       strlower(remote_machine);
  84.       if (p) *p = 0;
  85.  
  86.       strcpy(local_machine,name1);
  87.       trim_string(local_machine," "," ");
  88.       p = strchr(local_machine,' ');
  89.       strlower(local_machine);
  90.       if (p) *p = 0;
  91.  
  92.       add_session_user(remote_machine);
  93.  
  94.       reload_services(True);
  95.       reopen_logs();
  96.  
  97.       break;
  98.     case 0x85: /* session keepalive */
  99.     default:
  100.       return(0);
  101.     }
  102.   
  103.   DEBUG(5,("%s init msg_type=0x%x msg_flags=0x%x\n",timestring(),msg_type,msg_flags));
  104.   
  105.   return(outsize);
  106. }
  107.  
  108.  
  109. /*******************************************************************
  110. work out what error to give to a failed connection
  111. ********************************************************************/
  112. static int connection_error(char *inbuf,char *outbuf,int connection_num)
  113. {
  114.   switch (connection_num)
  115.     {
  116.     case -8:
  117.       return(ERROR(ERRSRV,ERRnoresource));
  118.     case -7:
  119.       return(ERROR(ERRSRV,ERRbaduid));
  120.     case -6:
  121.       return(ERROR(ERRSRV,ERRinvdevice));
  122.     case -5:
  123.       return(ERROR(ERRSRV,ERRinvnetname));
  124.     case -4:
  125.       return(ERROR(ERRSRV,ERRaccess));
  126.     case -3:
  127.       return(ERROR(ERRDOS,ERRnoipc));
  128.     case -2:
  129.       return(ERROR(ERRSRV,ERRinvnetname));
  130.     }
  131.   return(ERROR(ERRSRV,ERRbadpw));
  132. }
  133.  
  134.  
  135. /****************************************************************************
  136.   reply to a tcon
  137. ****************************************************************************/
  138. int reply_tcon(char *inbuf,char *outbuf)
  139. {
  140.   pstring service;
  141.   pstring user;
  142.   pstring password;
  143.   pstring dev;
  144.   int connection_num;
  145.   int outsize = 0;
  146.   int uid = SVAL(inbuf,smb_uid);
  147.   int vuid;
  148.   int pwlen;
  149.  
  150.   *service = *user = *password = *dev = 0;
  151.  
  152.   vuid = valid_uid(uid);
  153.   
  154.   parse_connect(inbuf,service,user,password,&pwlen,dev);
  155.  
  156.   connection_num = make_connection(service,user,password,pwlen,dev,vuid);
  157.   
  158.   if (connection_num < 0)
  159.     return(connection_error(inbuf,outbuf,connection_num));
  160.   
  161.   outsize = set_message(outbuf,2,0,True);
  162.   SSVAL(outbuf,smb_vwv0,maxxmit);
  163.   SSVAL(outbuf,smb_vwv1,connection_num);
  164.   SSVAL(outbuf,smb_tid,connection_num);
  165.   
  166.   DEBUG(3,("%s tcon service=%s user=%s cnum=%d\n",timestring(),service,user,connection_num));
  167.   
  168.   return(outsize);
  169. }
  170.  
  171.  
  172. /****************************************************************************
  173.   reply to a tcon and X
  174. ****************************************************************************/
  175. int reply_tcon_and_X(char *inbuf,char *outbuf,int length,int bufsize)
  176. {
  177.   pstring service;
  178.   pstring user;
  179.   pstring password;
  180.   pstring devicename;
  181.   int connection_num;
  182.   int outsize = 0;
  183.   int uid = SVAL(inbuf,smb_uid);
  184.   int vuid;
  185.   int smb_com2 = SVAL(inbuf,smb_vwv0);
  186.   int smb_off2 = SVAL(inbuf,smb_vwv1);
  187.   int passlen = SVAL(inbuf,smb_vwv3);
  188.  
  189.   *service = *user = *password = *devicename = 0;
  190.  
  191.   /* we might have to close an old one */
  192.   if ((SVAL(inbuf,smb_vwv2) & 0x1) != 0)
  193.     close_cnum(SVAL(inbuf,smb_tid),uid);
  194.   
  195.   vuid = valid_uid(uid);
  196.   
  197.   {
  198.     char *path;
  199.     char *p;
  200.     memcpy(password,smb_buf(inbuf),passlen);
  201.     password[passlen]=0;
  202.     path = smb_buf(inbuf) + passlen;
  203.     DEBUG(4,("parsing net-path %s, passlen=%d\n",path,passlen));
  204.     strcpy(service,path+2);
  205.     p = strchr(service,'\\');
  206.     if (!p)
  207.       return(ERROR(ERRSRV,ERRinvnetname));
  208.     *p = 0;
  209.     strcpy(service,p+1);
  210.     p = strchr(service,'%');
  211.     if (p)
  212.       {
  213.     *p++ = 0;
  214.     strcpy(user,p);
  215.       }
  216.     StrnCpy(devicename,path + strlen(path) + 1,6);
  217.     DEBUG(4,("Got device type %s\n",devicename));
  218.   }
  219.  
  220.   connection_num = make_connection(service,user,password,passlen,devicename,vuid);
  221.   
  222.   if (connection_num < 0)
  223.     return(connection_error(inbuf,outbuf,connection_num));
  224.  
  225.   outsize = set_message(outbuf,2,strlen(devicename)+1,True);
  226.   
  227.   DEBUG(3,("%s tconX service=%s user=%s cnum=%d\n",timestring(),service,user,connection_num));
  228.   
  229.   /* set the incoming and outgoing tid to the just created one */
  230.   SSVAL(inbuf,smb_tid,connection_num);
  231.   SSVAL(outbuf,smb_tid,connection_num);
  232.  
  233.   CVAL(outbuf,smb_vwv0) = smb_com2;
  234.   SSVAL(outbuf,smb_vwv1,(chain_size + outsize)-4);
  235.  
  236.   strcpy(smb_buf(outbuf),devicename);
  237.  
  238.   if (smb_com2 != 0xFF)
  239.     outsize += chain_reply(smb_com2,inbuf,inbuf+smb_off2+4,
  240.                outbuf,outbuf+outsize,
  241.                length,bufsize);
  242.  
  243.   return(outsize);
  244. }
  245.  
  246.  
  247. /****************************************************************************
  248.   reply to an unknown type
  249. ****************************************************************************/
  250. int reply_unknown(char *inbuf,char *outbuf)
  251. {
  252.   int cnum;
  253.   int type;
  254.   cnum = SVAL(inbuf,smb_tid);
  255.   type = CVAL(inbuf,smb_com);
  256.   
  257.   DEBUG(0,("%s unknown command type (%s): cnum=%d type=%d (0x%X)\n",
  258.     timestring(),
  259.     smb_fn_name(type),
  260.     cnum,type,type));
  261.   
  262.   return(ERROR(ERRSRV,ERRunknownsmb));
  263. }
  264.  
  265.  
  266. /****************************************************************************
  267.   reply to an ioctl
  268. ****************************************************************************/
  269. int reply_ioctl(char *inbuf,char *outbuf)
  270. {
  271.   DEBUG(3,("ignoring ioctl\n"));
  272.   
  273.   return(ERROR(ERRSRV,ERRnosupport));
  274. }
  275.  
  276.  
  277. /****************************************************************************
  278. reply to a session setup command
  279. ****************************************************************************/
  280. int reply_sesssetup_and_X(char *inbuf,char *outbuf,int length,int bufsize)
  281. {
  282.   int outsize = 0;
  283.   int sess_uid;
  284.   int gid;
  285.   int   smb_com2;
  286.   int   smb_off2;       
  287.   int   smb_bufsize;    
  288.   int   smb_mpxmax;     
  289.   int   smb_vc_num;     
  290.   uint32   smb_sesskey;    
  291.   int   smb_apasslen;   
  292.   pstring smb_apasswd;
  293.   int   smb_ntpasslen = 0;   
  294.   pstring smb_ntpasswd;
  295.   BOOL valid_nt_password = False;
  296.   pstring user;
  297.   BOOL guest=False;
  298.  
  299.   *smb_apasswd = 0;
  300.   
  301.   sess_uid = SVAL(inbuf,smb_uid);
  302.   smb_com2 = CVAL(inbuf,smb_vwv0);
  303.   smb_off2 = SVAL(inbuf,smb_vwv1);
  304.   smb_bufsize = SVAL(inbuf,smb_vwv2);
  305.   smb_mpxmax = SVAL(inbuf,smb_vwv3);
  306.   smb_vc_num = SVAL(inbuf,smb_vwv4);
  307.   smb_sesskey = IVAL(inbuf,smb_vwv5);
  308.  
  309.   if (Protocol < PROTOCOL_NT1) {
  310.     smb_apasslen = SVAL(inbuf,smb_vwv7);
  311.     memcpy(smb_apasswd,smb_buf(inbuf),smb_apasslen);
  312.     StrnCpy(user,smb_buf(inbuf)+smb_apasslen,sizeof(user)-1);
  313.   } else {
  314.     uint16 passlen1 = SVAL(inbuf,smb_vwv7);
  315.     uint16 passlen2 = SVAL(inbuf,smb_vwv8);
  316.     BOOL doencrypt = SMBENCRYPT();
  317.     char *p = smb_buf(inbuf);
  318.     if (passlen1 > 256) passlen1 = 0;
  319.     if (passlen2 > 256) passlen2 = 0; /* I don't know why NT gives weird 
  320.                     lengths sometimes */
  321.     if(doencrypt) {
  322.       /* Save the lanman2 password and the NT md4 password. */
  323.       smb_apasslen = passlen1;
  324.       memcpy(smb_apasswd,p,smb_apasslen);
  325.       smb_ntpasslen = passlen2;
  326.       memcpy(smb_ntpasswd,p+passlen1,smb_ntpasslen);
  327.     } else {
  328.       /* for Win95 */
  329.       if (passlen1 > passlen2) {
  330.     smb_apasslen = passlen1;
  331.     StrnCpy(smb_apasswd,p,smb_apasslen);
  332.       } else {
  333.     smb_apasslen = passlen2;
  334.     StrnCpy(smb_apasswd,p + passlen1,smb_apasslen);
  335.       }
  336.     }
  337.     p += passlen1 + passlen2;
  338.     strcpy(user,p); p = skip_string(p,1);
  339.     DEBUG(3,("Domain=[%s]  NativeOS=[%s] NativeLanMan=[%s]\n",
  340.          p,skip_string(p,1),skip_string(p,2)));
  341.   }
  342.  
  343.  
  344.   DEBUG(3,("sesssetupX:name=[%s]\n",user));
  345.  
  346.   if (!*user)
  347.     strcpy(user,lp_guestaccount(-1));
  348.  
  349.   strlower(user);
  350.  
  351.   strcpy(sesssetup_user,user);
  352.  
  353.   reload_services(True);
  354.  
  355.   add_session_user(user);
  356.  
  357.  
  358.   if (!(lp_security() == SEC_SERVER && server_validate(inbuf)) &&
  359.       !check_hosts_equiv(user))
  360.     {
  361.  
  362.       if (strequal(user,lp_guestaccount(-1)) && (*smb_apasswd == 0))
  363.     guest = True;
  364.   
  365.       /* now check if it's a valid username/password */
  366.       /* If an NT password was supplied try and validate with that
  367.      first. This is superior as the passwords are mixed case 128 length unicode */
  368.       if(smb_ntpasslen && !guest)
  369.     {
  370.       if(!password_ok(user,smb_ntpasswd,smb_ntpasslen,NULL,True))
  371.         DEBUG(0,("NT Password did not match ! Defaulting to Lanman\n"));
  372.       else
  373.         valid_nt_password = True;
  374.     } 
  375.       if (!valid_nt_password && !guest && !password_ok(user,smb_apasswd,smb_apasslen,NULL,False))
  376.     {
  377.       if (lp_security() >= SEC_USER) {
  378. #if (GUEST_SESSSETUP == 0)
  379.         return(ERROR(ERRSRV,ERRbadpw));
  380. #endif
  381. #if (GUEST_SESSSETUP == 1)
  382.         if (Get_Pwnam(user,True))
  383.           return(ERROR(ERRSRV,ERRbadpw));
  384. #endif
  385.       }
  386.        if (*smb_apasswd || !Get_Pwnam(user,True))
  387.         strcpy(user,lp_guestaccount(-1));
  388.       DEBUG(3,("Registered username %s for guest access\n",user));
  389.       guest = True;
  390.     }
  391.     }
  392.  
  393.   if (!Get_Pwnam(user,True)) {
  394.     DEBUG(3,("No such user %s - using guest account\n",user));
  395.     strcpy(user,lp_guestaccount(-1));
  396.     guest = True;
  397.   }
  398.  
  399.   if (!strequal(user,lp_guestaccount(-1)) &&
  400.       lp_servicenumber(user) < 0)      
  401.     {
  402.       int homes = lp_servicenumber(HOMES_NAME);
  403.       char *home = get_home_dir(user);
  404.       if (homes >= 0 && home)
  405.     lp_add_home(user,homes,home);
  406.     }
  407.  
  408.  
  409.   /* it's ok - setup a reply */
  410.   if (Protocol < PROTOCOL_NT1) {
  411.     outsize = set_message(outbuf,3,0,True);
  412.   } else {
  413.     char *p;
  414.     outsize = set_message(outbuf,3,3,True);
  415.     p = smb_buf(outbuf);
  416.     strcpy(p,"Unix"); p = skip_string(p,1);
  417.     strcpy(p,"Samba "); strcat(p,VERSION); p = skip_string(p,1);
  418.     strcpy(p,my_workgroup()); p = skip_string(p,1);
  419.     outsize = set_message(outbuf,3,PTR_DIFF(p,smb_buf(outbuf)),False);
  420.     /* perhaps grab OS version here?? */
  421.   }
  422.  
  423.   /* Set the correct uid in the outgoing and incoming packets
  424.      We will use this on future requests to determine which
  425.      user we should become.
  426.      */
  427.   {
  428.     struct passwd *pw = Get_Pwnam(user,False);
  429.     if (!pw) {
  430.       DEBUG(1,("Username %s is invalid on this system\n",user));
  431.       return(ERROR(ERRSRV,ERRbadpw));
  432.     }
  433.     gid = pw->pw_gid;
  434.     SSVAL(outbuf,smb_uid,(uint16)pw->pw_uid);
  435.     SSVAL(inbuf,smb_uid,(uint16)pw->pw_uid);
  436.   }
  437.  
  438.   CVAL(outbuf,smb_vwv0) = smb_com2;
  439.   SSVAL(outbuf,smb_vwv1,(chain_size+outsize)-4);
  440.  
  441.   if (guest)
  442.     SSVAL(outbuf,smb_vwv2,1);
  443.  
  444.   /* register the name and uid as being validated, so further connections
  445.      to a uid can get through without a password, on the same VC */
  446.   register_uid(SVAL(inbuf,smb_uid),gid,user,guest);
  447.  
  448.   maxxmit = MIN(maxxmit,smb_bufsize);
  449.  
  450.   if (smb_com2 != 0xFF)
  451.     outsize += chain_reply(smb_com2,inbuf,inbuf+smb_off2+4,
  452.                outbuf,outbuf+outsize,
  453.                length,bufsize);
  454.  
  455.   return(outsize);
  456. }
  457.  
  458.  
  459. /****************************************************************************
  460.   reply to a chkpth
  461. ****************************************************************************/
  462. int reply_chkpth(char *inbuf,char *outbuf)
  463. {
  464.   int outsize = 0;
  465.   int cnum,mode;
  466.   pstring name;
  467.   BOOL ok = False;
  468.   
  469.   cnum = SVAL(inbuf,smb_tid);
  470.   
  471.   strcpy(name,smb_buf(inbuf) + 1);
  472.   unix_convert(name,cnum);
  473.  
  474.   mode = SVAL(inbuf,smb_vwv0);
  475.  
  476.   if (check_name(name,cnum))
  477.     ok = directory_exist(name,NULL);
  478.  
  479.   if (!ok)
  480.     return(ERROR(ERRDOS,ERRbadpath));
  481.   
  482.   outsize = set_message(outbuf,0,0,True);
  483.   
  484.   DEBUG(3,("%s chkpth %s cnum=%d mode=%d\n",timestring(),name,cnum,mode));
  485.   
  486.   return(outsize);
  487. }
  488.  
  489.  
  490. /****************************************************************************
  491.   reply to a getatr
  492. ****************************************************************************/
  493. int reply_getatr(char *inbuf,char *outbuf)
  494. {
  495.   pstring fname;
  496.   int cnum;
  497.   int outsize = 0;
  498.   struct stat sbuf;
  499.   BOOL ok = False;
  500.   int mode=0;
  501.   uint32 size=0;
  502.   time_t mtime=0;
  503.   
  504.   cnum = SVAL(inbuf,smb_tid);
  505.  
  506.   strcpy(fname,smb_buf(inbuf) + 1);
  507.   unix_convert(fname,cnum);
  508.  
  509.   /* dos smetimes asks for a stat of "" - it returns a "hidden directory"
  510.      under WfWg - weird! */
  511.   if (! (*fname))
  512.     {
  513.       mode = aHIDDEN | aDIR;
  514.       if (!CAN_WRITE(cnum)) mode |= aRONLY;
  515.       size = 0;
  516.       mtime = 0;
  517.       ok = True;
  518.     }
  519.   else
  520.     if (check_name(fname,cnum))
  521.       {
  522.     if (sys_stat(fname,&sbuf) == 0)
  523.       {
  524.         mode = dos_mode(cnum,fname,&sbuf);
  525.         size = sbuf.st_size;
  526.         mtime = sbuf.st_mtime;
  527.         if (mode & aDIR)
  528.           size = 0;
  529.         ok = True;
  530.       }
  531.     else
  532.       DEBUG(3,("stat of %s failed (%s)\n",fname,strerror(errno)));
  533.     }
  534.   
  535.   if (!ok)
  536.     return(UNIXERROR(ERRDOS,ERRbadfile));
  537.   
  538.   outsize = set_message(outbuf,10,0,True);
  539.  
  540.   SSVAL(outbuf,smb_vwv0,mode);
  541.   put_dos_date3(outbuf,smb_vwv1,mtime);
  542.   SIVAL(outbuf,smb_vwv3,size);
  543.  
  544.   if (Protocol >= PROTOCOL_NT1) {
  545.     char *p = strrchr(fname,'/');
  546.     uint16 flg2 = SVAL(outbuf,smb_flg2);
  547.     if (!p) p = fname;
  548.     if (!is_8_3(fname))
  549.       SSVAL(outbuf,smb_flg2,flg2 | 0x40); /* IS_LONG_NAME */
  550.   }
  551.   
  552.   DEBUG(3,("%s getatr name=%s mode=%d size=%d\n",timestring(),fname,mode,size));
  553.   
  554.   return(outsize);
  555. }
  556.  
  557.  
  558. /****************************************************************************
  559.   reply to a setatr
  560. ****************************************************************************/
  561. int reply_setatr(char *inbuf,char *outbuf)
  562. {
  563.   pstring fname;
  564.   int cnum;
  565.   int outsize = 0;
  566.   BOOL ok=False;
  567.   int mode;
  568.   time_t mtime;
  569.   
  570.   cnum = SVAL(inbuf,smb_tid);
  571.   
  572.   strcpy(fname,smb_buf(inbuf) + 1);
  573.   unix_convert(fname,cnum);
  574.  
  575.   mode = SVAL(inbuf,smb_vwv0);
  576.   mtime = make_unix_date3(inbuf+smb_vwv1);
  577.   
  578.   if (directory_exist(fname,NULL))
  579.     mode |= aDIR;
  580.   if (check_name(fname,cnum))
  581.     ok =  (dos_chmod(cnum,fname,mode) == 0);
  582.   if (ok)
  583.     ok = set_filetime(fname,mtime);
  584.   
  585.   if (!ok)
  586.     return(UNIXERROR(ERRDOS,ERRnoaccess));
  587.   
  588.   outsize = set_message(outbuf,0,0,True);
  589.   
  590.   DEBUG(3,("%s setatr name=%s mode=%d\n",timestring(),fname,mode));
  591.   
  592.   return(outsize);
  593. }
  594.  
  595.  
  596. /****************************************************************************
  597.   reply to a dskattr
  598. ****************************************************************************/
  599. int reply_dskattr(char *inbuf,char *outbuf)
  600. {
  601.   int cnum;
  602.   int outsize = 0;
  603.   int dfree,dsize,bsize;
  604.   
  605.   cnum = SVAL(inbuf,smb_tid);
  606.   
  607.   sys_disk_free(".",&bsize,&dfree,&dsize);
  608.   
  609.   outsize = set_message(outbuf,5,0,True);
  610.   
  611.   SSVAL(outbuf,smb_vwv0,dsize);
  612.   SSVAL(outbuf,smb_vwv1,bsize/512);
  613.   SSVAL(outbuf,smb_vwv2,512);
  614.   SSVAL(outbuf,smb_vwv3,dfree);
  615.   
  616.   DEBUG(3,("%s dskattr cnum=%d dfree=%d\n",timestring(),cnum,dfree));
  617.   
  618.   return(outsize);
  619. }
  620.  
  621.  
  622. /****************************************************************************
  623.   reply to a search
  624.   Can be called from SMBsearch, SMBffirst or SMBfunique.
  625. ****************************************************************************/
  626. int reply_search(char *inbuf,char *outbuf)
  627. {
  628.   pstring mask;
  629.   pstring directory;
  630.   pstring fname;
  631.   int size,mode;
  632.   time_t date;
  633.   int dirtype;
  634.   int cnum;
  635.   int outsize = 0;
  636.   int numentries = 0;
  637.   BOOL finished = False;
  638.   int maxentries;
  639.   int i;
  640.   char *p;
  641.   BOOL ok = False;
  642.   int status_len;
  643.   char *path;
  644.   char status[21];
  645.   int dptr_num= -1;
  646.   BOOL check_descend = False;
  647.   BOOL expect_close = False;
  648.   BOOL can_open = True;
  649.  
  650.   *mask = *directory = *fname = 0;
  651.  
  652.   /* If we were called as SMBffirst then we must expect close. */
  653.   if(CVAL(inbuf,smb_com) == SMBffirst)
  654.     expect_close = True;
  655.   
  656.   cnum = SVAL(inbuf,smb_tid);
  657.  
  658.   outsize = set_message(outbuf,1,3,True);
  659.   maxentries = SVAL(inbuf,smb_vwv0); 
  660.   dirtype = SVAL(inbuf,smb_vwv1);
  661.   path = smb_buf(inbuf) + 1;
  662.   status_len = SVAL(smb_buf(inbuf),3 + strlen(path));
  663.  
  664.   
  665.   /* dirtype &= ~aDIR; */
  666.   
  667.   DEBUG(5,("path=%s status_len=%d\n",path,status_len));
  668.  
  669.   
  670.   if (status_len == 0)
  671.     {
  672.       pstring dir2;
  673.  
  674.       strcpy(directory,smb_buf(inbuf)+1);
  675.       strcpy(dir2,smb_buf(inbuf)+1);
  676.       unix_convert(directory,cnum);
  677.       unix_format(dir2);
  678.  
  679.       if (!check_name(directory,cnum))
  680.     can_open = False;
  681.  
  682.       p = strrchr(dir2,'/');
  683.       if (p == NULL) 
  684.     {strcpy(mask,dir2);*dir2 = 0;}
  685.       else
  686.     {*p = 0;strcpy(mask,p+1);}
  687.  
  688.       p = strrchr(directory,'/');
  689.       if (!p) 
  690.     *directory = 0;
  691.       else
  692.     *p = 0;
  693.  
  694.       if (strlen(directory) == 0)
  695.     strcpy(directory,"./");
  696.       bzero(status,21);
  697.       CVAL(status,0) = dirtype;
  698.     }
  699.   else
  700.     {
  701.       memcpy(status,smb_buf(inbuf) + 1 + strlen(path) + 4,21);
  702.       memcpy(mask,status+1,11);
  703.       mask[11] = 0;
  704.       dirtype = CVAL(status,0) & 0x1F;
  705.       Connections[cnum].dirptr = dptr_fetch(status+12,&dptr_num);      
  706.       if (!Connections[cnum].dirptr)
  707.     goto SearchEmpty;
  708.       string_set(&Connections[cnum].dirpath,dptr_path(dptr_num));
  709.       if (!case_sensitive)
  710.     strnorm(mask);
  711.     }
  712.  
  713.   /* turn strings of spaces into a . */  
  714.   {
  715.     trim_string(mask,NULL," ");
  716.     if ((p = strrchr(mask,' ')))
  717.       {
  718.     fstring ext;
  719.     strcpy(ext,p+1);
  720.     *p = 0;
  721.     trim_string(mask,NULL," ");
  722.     strcat(mask,".");
  723.     strcat(mask,ext);
  724.       }
  725.   }
  726.  
  727.   {
  728.     for (p=mask; *p; p++)
  729.       {
  730.     if (*p != '?' && *p != '*' && !isdoschar(*p))
  731.       {
  732.         DEBUG(5,("Invalid char [%c] in search mask?\n",*p));
  733.         *p = '?';
  734.       }
  735.       }
  736.   }
  737.  
  738.   if (!strchr(mask,'.') && strlen(mask)>8)
  739.     {
  740.       fstring tmp;
  741.       strcpy(tmp,&mask[8]);
  742.       mask[8] = '.';
  743.       mask[9] = 0;
  744.       strcat(mask,tmp);
  745.     }
  746.  
  747.   DEBUG(5,("mask=%s directory=%s\n",mask,directory));
  748.   
  749.   if (can_open)
  750.     {
  751.       p = smb_buf(outbuf) + 3;
  752.       
  753.       ok = True;
  754.       
  755.       if (status_len == 0)
  756.     {
  757.       dptr_num = dptr_create(cnum,directory,expect_close,SVAL(inbuf,smb_pid));
  758.       if (dptr_num < 0)
  759.         return(ERROR(ERRDOS,ERRnofids));
  760.     }
  761.  
  762.       DEBUG(4,("dptr_num is %d\n",dptr_num));
  763.  
  764.       if (ok)
  765.     {
  766.       if ((dirtype&0x1F) == aVOLID)
  767.         {      
  768.           memcpy(p,status,21);
  769.           make_dir_struct(p,"???????????",volume_label(SNUM(cnum)),0,aVOLID,0);
  770.           dptr_fill(p+12,dptr_num);
  771.           if (dptr_zero(p+12) && (status_len==0))
  772.         numentries = 1;
  773.           else
  774.         numentries = 0;
  775.           p += DIR_STRUCT_SIZE;
  776.         }
  777.       else 
  778.         {
  779.           DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",Connections[cnum].dirpath,lp_dontdescend(SNUM(cnum))));
  780.           if (in_list(Connections[cnum].dirpath,
  781.               lp_dontdescend(SNUM(cnum)),True))
  782.         check_descend = True;
  783.  
  784.           for (i=numentries;(i<maxentries) && !finished;i++)
  785.         {
  786.           finished = 
  787.             !get_dir_entry(cnum,mask,dirtype,fname,&size,&mode,&date,check_descend);
  788.           if (!finished)
  789.             {
  790.               memcpy(p,status,21);
  791.               make_dir_struct(p,mask,fname,size,mode,date);
  792.               dptr_fill(p+12,dptr_num);
  793.               numentries++;
  794.             }
  795.           p += DIR_STRUCT_SIZE;
  796.         }
  797.         }
  798.     }
  799.     }
  800.  
  801.  
  802.  SearchEmpty:
  803.  
  804.   if (numentries == 0 || !ok)
  805.     {
  806.       CVAL(outbuf,smb_rcls) = ERRDOS;
  807.       SSVAL(outbuf,smb_err,ERRnofiles);
  808.     }
  809.  
  810.   /* If we were called as SMBffirst with smb_search_id == NULL
  811.      and no entries were found then return error and close dirptr 
  812.      (X/Open spec) */
  813.  
  814.   if(ok && expect_close && numentries == 0 && status_len == 0)
  815.     {
  816.       CVAL(outbuf,smb_rcls) = ERRDOS;
  817.       SSVAL(outbuf,smb_err,ERRnofiles);
  818.       /* Also close the dptr - we know it's gone */
  819.       dptr_close(dptr_num);
  820.     }
  821.  
  822.   /* If we were called as SMBfunique, then we can close the dirptr now ! */
  823.   if(dptr_num >= 0 && CVAL(inbuf,smb_com) == SMBfunique)
  824.     dptr_close(dptr_num);
  825.  
  826.   SSVAL(outbuf,smb_vwv0,numentries);
  827.   SSVAL(outbuf,smb_vwv1,3 + numentries * DIR_STRUCT_SIZE);
  828.   CVAL(smb_buf(outbuf),0) = 5;
  829.   SSVAL(smb_buf(outbuf),1,numentries*DIR_STRUCT_SIZE);
  830.  
  831.   if (Protocol >= PROTOCOL_NT1) {
  832.     uint16 flg2 = SVAL(outbuf,smb_flg2);
  833.     SSVAL(outbuf,smb_flg2,flg2 | 0x40); /* IS_LONG_NAME */
  834.   }
  835.   
  836.   outsize += DIR_STRUCT_SIZE*numentries;
  837.   smb_setlen(outbuf,outsize - 4);
  838.   
  839.   if ((! *directory) && dptr_path(dptr_num))
  840.     sprintf(directory,"(%s)",dptr_path(dptr_num));
  841.  
  842.   DEBUG(4,("%s %s mask=%s path=%s cnum=%d dtype=%d nument=%d of %d\n",
  843.     timestring(),
  844.     smb_fn_name(CVAL(inbuf,smb_com)), 
  845.     mask,directory,cnum,dirtype,numentries,maxentries));
  846.  
  847.   return(outsize);
  848. }
  849.  
  850.  
  851. /****************************************************************************
  852.   reply to a fclose (stop directory search)
  853. ****************************************************************************/
  854. int reply_fclose(char *inbuf,char *outbuf)
  855. {
  856.   int cnum;
  857.   int outsize = 0;
  858.   int status_len;
  859.   char *path;
  860.   char status[21];
  861.   int dptr_num= -1;
  862.  
  863.   cnum = SVAL(inbuf,smb_tid);
  864.  
  865.   outsize = set_message(outbuf,1,0,True);
  866.   path = smb_buf(inbuf) + 1;
  867.   status_len = SVAL(smb_buf(inbuf),3 + strlen(path));
  868.  
  869.   
  870.   if (status_len == 0)
  871.     return(ERROR(ERRSRV,ERRsrverror));
  872.  
  873.   memcpy(status,smb_buf(inbuf) + 1 + strlen(path) + 4,21);
  874.  
  875.   if(dptr_fetch(status+12,&dptr_num)) {
  876.     /*  Close the dptr - we know it's gone */
  877.     dptr_close(dptr_num);
  878.   }
  879.  
  880.   SSVAL(outbuf,smb_vwv0,0);
  881.  
  882.   DEBUG(3,("%s search close cnum=%d\n",timestring(),cnum));
  883.  
  884.   return(outsize);
  885. }
  886.  
  887.  
  888. /****************************************************************************
  889.   reply to an open
  890. ****************************************************************************/
  891. int reply_open(char *inbuf,char *outbuf)
  892. {
  893.   pstring fname;
  894.   int cnum;
  895.   int fnum = -1;
  896.   int outsize = 0;
  897.   int fmode=0;
  898.   int share_mode;
  899.   int size = 0;
  900.   time_t mtime=0;
  901.   int unixmode;
  902.   int rmode=0;
  903.   struct stat sbuf;
  904.   
  905.   cnum = SVAL(inbuf,smb_tid);
  906.  
  907.   share_mode = SVAL(inbuf,smb_vwv0);
  908.  
  909.   strcpy(fname,smb_buf(inbuf)+1);
  910.   unix_convert(fname,cnum);
  911.     
  912.   fnum = find_free_file();
  913.   if (fnum < 0)
  914.     return(ERROR(ERRSRV,ERRnofids));
  915.  
  916.   if (!check_name(fname,cnum))
  917.     return(UNIXERROR(ERRDOS,ERRnoaccess));
  918.   
  919.   unixmode = unix_mode(cnum,aARCH);
  920.       
  921.   open_file_shared(fnum,cnum,fname,share_mode,3,unixmode,&rmode,NULL);
  922.  
  923.   if (!Files[fnum].open)
  924.     return(UNIXERROR(ERRDOS,ERRnoaccess));
  925.  
  926.   if (fstat(Files[fnum].fd,&sbuf) != 0) {
  927.     close_file(fnum);
  928.     return(ERROR(ERRDOS,ERRnoaccess));
  929.   }
  930.     
  931.   size = sbuf.st_size;
  932.   fmode = dos_mode(cnum,fname,&sbuf);
  933.   mtime = sbuf.st_mtime;
  934.  
  935.   if (fmode & aDIR) {
  936.     DEBUG(3,("attempt to open a directory %s\n",fname));
  937.     close_file(fnum);
  938.     return(ERROR(ERRDOS,ERRnoaccess));
  939.   }
  940.   
  941.   outsize = set_message(outbuf,7,0,True);
  942.   SSVAL(outbuf,smb_vwv0,fnum);
  943.   SSVAL(outbuf,smb_vwv1,fmode);
  944.   put_dos_date3(outbuf,smb_vwv2,mtime);
  945.   SIVAL(outbuf,smb_vwv4,size);
  946.   SSVAL(outbuf,smb_vwv6,rmode);
  947.     
  948.   return(outsize);
  949. }
  950.  
  951.  
  952. /****************************************************************************
  953.   reply to an open and X
  954. ****************************************************************************/
  955. int reply_open_and_X(char *inbuf,char *outbuf,int length,int bufsize)
  956. {
  957.   pstring fname;
  958.   int cnum = SVAL(inbuf,smb_tid);
  959.   int fnum = -1;
  960.   int outsize = 0;
  961.   int openmode = 0;
  962.   int smb_com2 = CVAL(inbuf,smb_vwv0);
  963.   int smb_off2 = SVAL(inbuf,smb_vwv1);
  964.   int smb_mode = SVAL(inbuf,smb_vwv3);
  965.   int smb_attr = SVAL(inbuf,smb_vwv5);
  966. #if 0
  967.   int open_flags = SVAL(inbuf,smb_vwv2);
  968.   int smb_sattr = SVAL(inbuf,smb_vwv4); 
  969.   uint32 smb_time = make_unix_date3(inbuf+smb_vwv6);
  970. #endif
  971.   int smb_ofun = SVAL(inbuf,smb_vwv8);
  972.   int unixmode;
  973.   int size=0,fmode=0,mtime=0,rmode=0;
  974.   struct stat sbuf;
  975.   int smb_action = 0;
  976.  
  977.   /* XXXX we need to handle passed times, sattr and flags */
  978.  
  979.   strcpy(fname,smb_buf(inbuf));
  980.   unix_convert(fname,cnum);
  981.     
  982.   /* now add create and trunc bits */
  983.   if (smb_ofun & 0x10)
  984.     openmode |= O_CREAT;
  985.   if ((smb_ofun & 0x3) == 2)
  986.     openmode |= O_TRUNC;
  987.   
  988.   fnum = find_free_file();
  989.   if (fnum < 0)
  990.     return(ERROR(ERRSRV,ERRnofids));
  991.  
  992.   if (!check_name(fname,cnum))
  993.     return(UNIXERROR(ERRDOS,ERRnoaccess));
  994.  
  995.   unixmode = unix_mode(cnum,smb_attr);
  996.       
  997.   open_file_shared(fnum,cnum,fname,smb_mode,smb_ofun,unixmode,
  998.            &rmode,&smb_action);
  999.       
  1000.   if (!Files[fnum].open)
  1001.     return(UNIXERROR(ERRDOS,ERRnoaccess));
  1002.  
  1003.   if (fstat(Files[fnum].fd,&sbuf) != 0) {
  1004.     close_file(fnum);
  1005.     return(ERROR(ERRDOS,ERRnoaccess));
  1006.   }
  1007.  
  1008.   size = sbuf.st_size;
  1009.   fmode = dos_mode(cnum,fname,&sbuf);
  1010.   mtime = sbuf.st_mtime;
  1011.   if (fmode & aDIR) {
  1012.     close_file(fnum);
  1013.     return(ERROR(ERRDOS,ERRnoaccess));
  1014.   }
  1015.  
  1016.   outsize = set_message(outbuf,15,0,True);
  1017.   CVAL(outbuf,smb_vwv0) = smb_com2;
  1018.   SSVAL(outbuf,smb_vwv1,(chain_size+outsize)-4);
  1019.   SSVAL(outbuf,smb_vwv2,fnum);
  1020.   SSVAL(outbuf,smb_vwv3,fmode);
  1021.   put_dos_date3(outbuf,smb_vwv4,mtime);
  1022.   SIVAL(outbuf,smb_vwv6,size);
  1023.   SSVAL(outbuf,smb_vwv8,rmode);
  1024.   SSVAL(outbuf,smb_vwv11,smb_action);
  1025.  
  1026.   chain_fnum = fnum;
  1027.  
  1028.   if (smb_com2 != 0xFF)
  1029.     outsize += chain_reply(smb_com2,inbuf,inbuf+smb_off2+4,
  1030.                outbuf,outbuf+outsize,
  1031.                length,bufsize);
  1032.  
  1033.   chain_fnum = -1;
  1034.   
  1035.   return(outsize);
  1036. }
  1037.  
  1038.  
  1039. /****************************************************************************
  1040.   reply to a SMBulogoffX
  1041. ****************************************************************************/
  1042. int reply_ulogoffX(char *inbuf,char *outbuf,int length,int bufsize)
  1043. {
  1044.   int outsize = 0;
  1045.   int smb_com2 = CVAL(inbuf,smb_vwv0);
  1046.   int smb_off2 = SVAL(inbuf,smb_vwv1);
  1047.   int uid = SVAL(inbuf,smb_uid);
  1048.  
  1049.   invalidate_uid(uid);
  1050.  
  1051.   outsize = set_message(outbuf,2,0,True);
  1052.   CVAL(outbuf,smb_vwv0) = smb_com2;
  1053.   SSVAL(outbuf,smb_vwv1,(chain_size+outsize)-4);
  1054.  
  1055.   DEBUG(3,("%s ulogoffX uid=%d\n",timestring(),uid));
  1056.  
  1057.   if (smb_com2 != 0xFF)
  1058.     outsize += chain_reply(smb_com2,inbuf,inbuf+smb_off2+4,
  1059.                outbuf,outbuf+outsize,
  1060.                length,bufsize);
  1061.  
  1062.   
  1063.   return(outsize);
  1064. }
  1065.  
  1066.  
  1067. /****************************************************************************
  1068.   reply to a mknew
  1069. ****************************************************************************/
  1070. int reply_mknew(char *inbuf,char *outbuf)
  1071. {
  1072.   pstring fname;
  1073.   int cnum,com;
  1074.   int fnum = -1;
  1075.   int outsize = 0;
  1076.   int createmode;
  1077.   mode_t unixmode;
  1078.   
  1079.   com = SVAL(inbuf,smb_com);
  1080.   cnum = SVAL(inbuf,smb_tid);
  1081.  
  1082.   createmode = SVAL(inbuf,smb_vwv0);
  1083.   strcpy(fname,smb_buf(inbuf)+1);
  1084.   unix_convert(fname,cnum);
  1085.  
  1086.   if (createmode & aVOLID)
  1087.     {
  1088.       DEBUG(0,("Attempt to create file (%s) with volid set - please report this\n",fname));
  1089.     }
  1090.   
  1091.   unixmode = unix_mode(cnum,createmode);
  1092.   
  1093.   if (com == SMBmknew && file_exist(fname,NULL))
  1094.     return(ERROR(ERRDOS,ERRfilexists));
  1095.     
  1096.   fnum = find_free_file();
  1097.   if (fnum < 0)
  1098.     return(ERROR(ERRSRV,ERRnofids));
  1099.  
  1100.   if (!check_name(fname,cnum))
  1101.     return(UNIXERROR(ERRDOS,ERRnoaccess));
  1102.  
  1103.   open_file(fnum,cnum,fname,O_RDWR | O_CREAT | O_TRUNC,unixmode);
  1104.   
  1105.   if (!Files[fnum].open)
  1106.     return(UNIXERROR(ERRDOS,ERRnoaccess));
  1107.   
  1108.   outsize = set_message(outbuf,1,0,True);
  1109.   SSVAL(outbuf,smb_vwv0,fnum);
  1110.   
  1111.   DEBUG(2,("new file %s\n",fname));
  1112.   DEBUG(3,("%s mknew %s fd=%d fnum=%d cnum=%d dmode=%d umode=%o\n",timestring(),fname,Files[fnum].fd,fnum,cnum,createmode,unixmode));
  1113.   
  1114.   return(outsize);
  1115. }
  1116.  
  1117.  
  1118. /****************************************************************************
  1119.   reply to a create temporary file
  1120. ****************************************************************************/
  1121. int reply_ctemp(char *inbuf,char *outbuf)
  1122. {
  1123.   pstring fname;
  1124.   pstring fname2;
  1125.   int cnum;
  1126.   int fnum = -1;
  1127.   int outsize = 0;
  1128.   int createmode;
  1129.   mode_t unixmode;
  1130.   
  1131.   cnum = SVAL(inbuf,smb_tid);
  1132.   createmode = SVAL(inbuf,smb_vwv0);
  1133.   sprintf(fname,"%s/TMXXXXXX",smb_buf(inbuf)+1);
  1134.   unix_convert(fname,cnum);
  1135.   
  1136.   unixmode = unix_mode(cnum,createmode);
  1137.   
  1138.   fnum = find_free_file();
  1139.   if (fnum < 0)
  1140.     return(ERROR(ERRSRV,ERRnofids));
  1141.  
  1142.   if (!check_name(fname,cnum))
  1143.     return(UNIXERROR(ERRDOS,ERRnoaccess));
  1144.  
  1145.   strcpy(fname2,(char *)mktemp(fname));
  1146.  
  1147.   open_file(fnum,cnum,fname2,O_RDWR | O_CREAT | O_TRUNC,unixmode);
  1148.  
  1149.   if (!Files[fnum].open)
  1150.     return(UNIXERROR(ERRDOS,ERRnoaccess));
  1151.  
  1152.   outsize = set_message(outbuf,1,2 + strlen(fname2),True);
  1153.   SSVAL(outbuf,smb_vwv0,fnum);
  1154.   CVAL(smb_buf(outbuf),0) = 4;
  1155.   strcpy(smb_buf(outbuf) + 1,fname2);
  1156.   
  1157.   DEBUG(2,("created temp file %s\n",fname2));
  1158.   DEBUG(3,("%s ctemp %s fd=%d fnum=%d cnum=%d dmode=%d umode=%o\n",timestring(),fname2,Files[fnum].fd,fnum,cnum,createmode,unixmode));
  1159.   
  1160.   return(outsize);
  1161. }
  1162.  
  1163.  
  1164. /*******************************************************************
  1165. check if a user is allowed to delete a file
  1166. ********************************************************************/
  1167. static BOOL can_delete(char *fname,int cnum,int dirtype)
  1168. {
  1169.   struct stat sbuf;
  1170.   int fmode;
  1171.  
  1172.   if (!CAN_WRITE(cnum)) return(False);
  1173.  
  1174.   if (sys_lstat(fname,&sbuf) != 0) return(False);
  1175.   fmode = dos_mode(cnum,fname,&sbuf);
  1176.   if (fmode & aDIR) return(False);
  1177.   if (fmode & aRONLY) return(False);
  1178.   if ((fmode & ~dirtype) & (aHIDDEN | aSYSTEM))
  1179.     return(False);
  1180.   if (!check_file_sharing(cnum,fname)) return(False);
  1181.   return(True);
  1182. }
  1183.  
  1184. /****************************************************************************
  1185.   reply to a unlink
  1186. ****************************************************************************/
  1187. int reply_unlink(char *inbuf,char *outbuf)
  1188. {
  1189.   int outsize = 0;
  1190.   pstring name;
  1191.   int cnum;
  1192.   int dirtype;
  1193.   pstring directory;
  1194.   pstring mask;
  1195.   char *p;
  1196.   int count=0;
  1197.   int error = ERRnoaccess;
  1198.   BOOL has_wild;
  1199.   BOOL exists=False;
  1200.  
  1201.   *directory = *mask = 0;
  1202.  
  1203.   cnum = SVAL(inbuf,smb_tid);
  1204.   dirtype = SVAL(inbuf,smb_vwv0);
  1205.   
  1206.   strcpy(name,smb_buf(inbuf) + 1);
  1207.    
  1208.   DEBUG(3,("reply_unlink : %s\n",name));
  1209.    
  1210.   unix_convert(name,cnum);
  1211.  
  1212.   p = strrchr(name,'/');
  1213.   if (!p) {
  1214.     strcpy(directory,"./");
  1215.     strcpy(mask,name);
  1216.   } else {
  1217.     *p = 0;
  1218.     strcpy(directory,name);
  1219.     strcpy(mask,p+1);
  1220.   }
  1221.  
  1222.   if (is_mangled(mask))
  1223.     check_mangled_stack(mask);
  1224.  
  1225.   has_wild = strchr(mask,'*') || strchr(mask,'?');
  1226.  
  1227.   if (!has_wild) {
  1228.     strcat(directory,"/");
  1229.     strcat(directory,mask);
  1230.     if (can_delete(directory,cnum,dirtype) && !sys_unlink(directory)) count++;
  1231.     if (!count) exists = file_exist(directory,NULL);    
  1232.   } else {
  1233.     void *dirptr = NULL;
  1234.     char *dname;
  1235.  
  1236.     if (check_name(directory,cnum))
  1237.       dirptr = OpenDir(directory);
  1238.  
  1239.     if (dirptr)
  1240.       {
  1241.     error = ERRbadfile;
  1242.  
  1243.     if (strequal(mask,"????????.???"))
  1244.       strcpy(mask,"*");
  1245.  
  1246.     while ((dname = ReadDirName(dirptr)))
  1247.       {
  1248.         pstring fname;
  1249.         strcpy(fname,dname);
  1250.         
  1251.         if(!mask_match(fname, mask, case_sensitive, False)) continue;
  1252.  
  1253.         error = ERRnoaccess;
  1254.         sprintf(fname,"%s/%s",directory,dname);
  1255.         if (!can_delete(fname,cnum,dirtype)) continue;
  1256.         if (!sys_unlink(fname)) count++;
  1257.         DEBUG(3,("reply_unlink : doing unlink on %s\n",fname));
  1258.       }
  1259.     CloseDir(dirptr);
  1260.       }
  1261.   }
  1262.   
  1263.   if (count == 0) {
  1264.     if (exists)
  1265.       return(ERROR(ERRDOS,error));
  1266.     else
  1267.       return(UNIXERROR(ERRDOS,error));
  1268.   }
  1269.   
  1270.   outsize = set_message(outbuf,0,0,True);
  1271.   
  1272.   return(outsize);
  1273. }
  1274.  
  1275.  
  1276. /****************************************************************************
  1277.    reply to a readbraw (core+ protocol)
  1278. ****************************************************************************/
  1279. int reply_readbraw(char *inbuf, char *outbuf)
  1280. {
  1281.   int cnum,maxcount,mincount,fnum;
  1282.   int nread = 0;
  1283.   int startpos;
  1284.   char *header = outbuf;
  1285.   int ret=0;
  1286.   int fd;
  1287.   char *fname;
  1288.  
  1289.   cnum = SVAL(inbuf,smb_tid);
  1290.   fnum = GETFNUM(inbuf,smb_vwv0);
  1291.  
  1292.   startpos = IVAL(inbuf,smb_vwv1);
  1293.   maxcount = SVAL(inbuf,smb_vwv3);
  1294.   mincount = SVAL(inbuf,smb_vwv4);
  1295.  
  1296.   /* ensure we don't overrun the packet size */
  1297.   maxcount = MIN(65535,maxcount);
  1298.   maxcount = MAX(mincount,maxcount);
  1299.  
  1300.   if (!FNUM_OK(fnum,cnum) || !Files[fnum].can_read)
  1301.     {
  1302.       DEBUG(3,("fnum %d not open in readbraw - cache prime?\n",fnum));
  1303.       _smb_setlen(header,0);
  1304.       transfer_file(0,Client,0,header,4,0);
  1305.       return(-1);
  1306.     }
  1307.   else
  1308.     {
  1309.       fd = Files[fnum].fd;
  1310.       fname = Files[fnum].name;
  1311.     }
  1312.  
  1313.  
  1314.   if (!is_locked(fnum,cnum,maxcount,startpos))
  1315.     {
  1316.       int size = Files[fnum].size;
  1317.       int sizeneeded = startpos + maxcount;
  1318.         
  1319.       if (size < sizeneeded) {
  1320.     struct stat st;
  1321.     if (fstat(Files[fnum].fd,&st) == 0)
  1322.       size = st.st_size;
  1323.     if (!Files[fnum].can_write) 
  1324.       Files[fnum].size = size;
  1325.       }
  1326.  
  1327.       nread = MIN(maxcount,size - startpos);      
  1328.     }
  1329.  
  1330.   if (nread < mincount)
  1331.     nread = 0;
  1332.   
  1333.   DEBUG(3,("%s readbraw fnum=%d cnum=%d start=%d max=%d min=%d nread=%d\n",
  1334.        timestring(),
  1335.        fnum,cnum,startpos,
  1336.        maxcount,mincount,nread));
  1337.   
  1338. #if UNSAFE_READRAW
  1339.   {
  1340.     int predict=0;
  1341.     _smb_setlen(header,nread);
  1342.  
  1343.     if (!Files[fnum].can_write)
  1344.       predict = read_predict(fd,startpos,header+4,NULL,nread);
  1345.  
  1346.     if ((nread-predict) > 0)
  1347.       seek_file(fnum,startpos + predict);
  1348.     
  1349.     ret = transfer_file(fd,Client,nread-predict,header,4+predict,
  1350.             startpos+predict);
  1351.   }
  1352.  
  1353.   if (ret != nread+4)
  1354.     DEBUG(0,("ERROR: file read failure on %s at %d for %d bytes (%d)\n",
  1355.          fname,startpos,nread,ret));
  1356.  
  1357. #else
  1358.   ret = read_file(fnum,header+4,startpos,nread,nread,-1,False);
  1359.   if (ret < mincount) ret = 0;
  1360.  
  1361.   _smb_setlen(header,ret);
  1362.   transfer_file(0,Client,0,header,4+ret,0);
  1363. #endif
  1364.  
  1365.   DEBUG(5,("readbraw finished\n"));
  1366.   return -1;
  1367. }
  1368.  
  1369.  
  1370. /****************************************************************************
  1371.   reply to a lockread (core+ protocol)
  1372. ****************************************************************************/
  1373. int reply_lockread(char *inbuf,char *outbuf)
  1374. {
  1375.   int cnum,fnum;
  1376.   int nread = -1;
  1377.   char *data;
  1378.   int outsize = 0;
  1379.   uint32 startpos, numtoread;
  1380.   int eclass;
  1381.   uint32 ecode;
  1382.   
  1383.   cnum = SVAL(inbuf,smb_tid);
  1384.   fnum = GETFNUM(inbuf,smb_vwv0);
  1385.  
  1386.   CHECK_FNUM(fnum,cnum);
  1387.   CHECK_READ(fnum);
  1388.   CHECK_ERROR(fnum);
  1389.  
  1390.   numtoread = SVAL(inbuf,smb_vwv1);
  1391.   startpos = IVAL(inbuf,smb_vwv2);
  1392.   
  1393.   outsize = set_message(outbuf,5,3,True);
  1394.   numtoread = MIN(BUFFER_SIZE-outsize,numtoread);
  1395.   data = smb_buf(outbuf) + 3;
  1396.   
  1397.   if(!do_lock( fnum, cnum, numtoread, startpos, &eclass, &ecode))
  1398.     return (ERROR(eclass,ecode));
  1399.  
  1400.   nread = read_file(fnum,data,startpos,numtoread,numtoread,-1,False);
  1401.   
  1402.   if (nread < 0)
  1403.     return(UNIXERROR(ERRDOS,ERRnoaccess));
  1404.   
  1405.   outsize += nread;
  1406.   SSVAL(outbuf,smb_vwv0,nread);
  1407.   SSVAL(outbuf,smb_vwv5,nread+3);
  1408.   SSVAL(smb_buf(outbuf),1,nread);
  1409.   
  1410.   DEBUG(3,("%s lockread fnum=%d cnum=%d num=%d nread=%d\n",timestring(),fnum,cnum,numtoread,nread));
  1411.   
  1412.   return(outsize);
  1413. }
  1414.  
  1415.  
  1416. /****************************************************************************
  1417.   reply to a read
  1418. ****************************************************************************/
  1419. int reply_read(char *inbuf,char *outbuf)
  1420. {
  1421.   int cnum,numtoread,fnum;
  1422.   int nread = 0;
  1423.   char *data;
  1424.   int startpos;
  1425.   int outsize = 0;
  1426.   
  1427.   cnum = SVAL(inbuf,smb_tid);
  1428.   fnum = GETFNUM(inbuf,smb_vwv0);
  1429.  
  1430.   CHECK_FNUM(fnum,cnum);
  1431.   CHECK_READ(fnum);
  1432.   CHECK_ERROR(fnum);
  1433.  
  1434.   numtoread = SVAL(inbuf,smb_vwv1);
  1435.   startpos = IVAL(inbuf,smb_vwv2);
  1436.   
  1437.   outsize = set_message(outbuf,5,3,True);
  1438.   numtoread = MIN(BUFFER_SIZE-outsize,numtoread);
  1439.   data = smb_buf(outbuf) + 3;
  1440.   
  1441.   if (is_locked(fnum,cnum,numtoread,startpos))
  1442.     return(ERROR(ERRDOS,ERRlock));    
  1443.  
  1444.   if (numtoread > 0)
  1445.     nread = read_file(fnum,data,startpos,numtoread,numtoread,-1,False);
  1446.   
  1447.   if (nread < 0)
  1448.     return(UNIXERROR(ERRDOS,ERRnoaccess));
  1449.   
  1450.   outsize += nread;
  1451.   SSVAL(outbuf,smb_vwv0,nread);
  1452.   SSVAL(outbuf,smb_vwv5,nread+3);
  1453.   CVAL(smb_buf(outbuf),0) = 1;
  1454.   SSVAL(smb_buf(outbuf),1,nread);
  1455.   
  1456.   DEBUG(3,("%s read fnum=%d cnum=%d num=%d nread=%d\n",timestring(),fnum,cnum,numtoread,nread));
  1457.   
  1458.   return(outsize);
  1459. }
  1460.  
  1461.  
  1462. /****************************************************************************
  1463.   reply to a read and X
  1464. ****************************************************************************/
  1465. int reply_read_and_X(char *inbuf,char *outbuf,int length,int bufsize)
  1466. {
  1467.   int smb_com2 = CVAL(inbuf,smb_vwv0);
  1468.   int smb_off2 = SVAL(inbuf,smb_vwv1);
  1469.   int fnum = GETFNUM(inbuf,smb_vwv2);
  1470.   uint32 smb_offs = IVAL(inbuf,smb_vwv3);
  1471.   int smb_maxcnt = SVAL(inbuf,smb_vwv5);
  1472.   int smb_mincnt = SVAL(inbuf,smb_vwv6);
  1473.   int cnum;
  1474.   int nread = -1;
  1475.   char *data;
  1476.   int outsize = 0;
  1477.   BOOL ok = False;
  1478.  
  1479.   cnum = SVAL(inbuf,smb_tid);
  1480.  
  1481.   CHECK_FNUM(fnum,cnum);
  1482.   CHECK_READ(fnum);
  1483.   CHECK_ERROR(fnum);
  1484.  
  1485.   outsize = set_message(outbuf,12,0,True);
  1486.   data = smb_buf(outbuf);
  1487.  
  1488.   if (is_locked(fnum,cnum,smb_maxcnt,smb_offs))
  1489.     return(ERROR(ERRDOS,ERRlock));
  1490.   nread = read_file(fnum,data,smb_offs,smb_maxcnt,smb_maxcnt,-1,False);
  1491.   ok = True;
  1492.   
  1493.   if (nread < 0)
  1494.     return(UNIXERROR(ERRDOS,ERRnoaccess));
  1495.   
  1496.   outsize += nread;
  1497.   CVAL(outbuf,smb_vwv0) = smb_com2;
  1498.   SSVAL(outbuf,smb_vwv1,(outsize+chain_size)-4);
  1499.   SSVAL(outbuf,smb_vwv5,nread);
  1500.   SSVAL(outbuf,smb_vwv6,smb_offset(data,outbuf) + chain_size);
  1501.   SSVAL(smb_buf(outbuf),-2,nread);
  1502.   
  1503.   DEBUG(3,("%s readX fnum=%d cnum=%d min=%d max=%d nread=%d com2=%d off2=%d\n",
  1504.     timestring(),fnum,cnum,
  1505.     smb_mincnt,smb_maxcnt,nread,smb_com2,smb_off2));
  1506.  
  1507.   chain_fnum = fnum;
  1508.  
  1509.   if (smb_com2 != 0xFF)
  1510.     outsize += chain_reply(smb_com2,inbuf,inbuf+smb_off2+4,
  1511.                outbuf,outbuf+outsize,
  1512.                length,bufsize);
  1513.   
  1514.   chain_fnum = -1;
  1515.   
  1516.   return(outsize);
  1517. }
  1518.  
  1519.  
  1520. /****************************************************************************
  1521.   reply to a writebraw (core+ or LANMAN1.0 protocol)
  1522. ****************************************************************************/
  1523. int reply_writebraw(char *inbuf,char *outbuf)
  1524. {
  1525.   int nwritten=0;
  1526.   int total_written=0;
  1527.   int numtowrite=0;
  1528.   int cnum,fnum;
  1529.   int outsize = 0;
  1530.   long startpos;
  1531.   char *data=NULL;
  1532.   BOOL write_through;
  1533.   int tcount;
  1534.  
  1535.   cnum = SVAL(inbuf,smb_tid);
  1536.   fnum = GETFNUM(inbuf,smb_vwv0);
  1537.  
  1538.   CHECK_FNUM(fnum,cnum);
  1539.   CHECK_WRITE(fnum);
  1540.   CHECK_ERROR(fnum);
  1541.   
  1542.   tcount = IVAL(inbuf,smb_vwv1);
  1543.   startpos = IVAL(inbuf,smb_vwv3);
  1544.   write_through = BITSETW(inbuf+smb_vwv7,0);
  1545.  
  1546.   /* We have to deal with slightly different formats depending
  1547.      on whether we are using the core+ or lanman1.0 protocol */
  1548.   if(Protocol <= PROTOCOL_COREPLUS) {
  1549.     numtowrite = SVAL(smb_buf(inbuf),-2);
  1550.     data = smb_buf(inbuf);
  1551.   } else {
  1552.     numtowrite = SVAL(inbuf,smb_vwv10);
  1553.     data = smb_base(inbuf) + SVAL(inbuf, smb_vwv11);
  1554.   }
  1555.  
  1556.   /* force the error type */
  1557.   CVAL(inbuf,smb_com) = SMBwritec;
  1558.   CVAL(outbuf,smb_com) = SMBwritec;
  1559.  
  1560.   if (is_locked(fnum,cnum,tcount,startpos))
  1561.     return(ERROR(ERRDOS,ERRlock));
  1562.  
  1563.   if (seek_file(fnum,startpos) != startpos)
  1564.     DEBUG(0,("couldn't seek to %d in writebraw\n",startpos));
  1565.  
  1566.   if (numtowrite>0)
  1567.     nwritten = write_data(Files[fnum].fd,data,numtowrite);
  1568.   
  1569.   DEBUG(3,("%s writebraw1 fnum=%d cnum=%d start=%d num=%d wrote=%d sync=%d\n",
  1570.        timestring(),fnum,cnum,startpos,numtowrite,nwritten,write_through));
  1571.  
  1572.   if (nwritten < numtowrite) 
  1573.     return(UNIXERROR(ERRHRD,ERRdiskfull));
  1574.  
  1575.   total_written = nwritten;
  1576.  
  1577.   /* Return a message to the redirector to tell it
  1578.      to send more bytes */
  1579.   CVAL(outbuf,smb_com) = SMBwritebraw;
  1580.   SSVALS(outbuf,smb_vwv0,-1);
  1581.   outsize = set_message(outbuf,Protocol>PROTOCOL_COREPLUS?1:0,0,True);
  1582.   send_smb(Client,outbuf);
  1583.   
  1584.   /* Now read the raw data into the buffer and write it */
  1585.   if(read_smb_length(Client,inbuf,0) == -1) {
  1586.     exit_server("secondary writebraw failed");
  1587.   }
  1588.   
  1589.   /* Even though this is not an smb message, smb_len
  1590.      returns the generic length of an smb message */
  1591.   numtowrite = smb_len(inbuf);
  1592.  
  1593.   if (tcount > nwritten+numtowrite) {
  1594.     DEBUG(3,("Client overestimated the write %d %d %d\n",
  1595.          tcount,nwritten,numtowrite));
  1596.   }
  1597.  
  1598.   nwritten = transfer_file(Client,Files[fnum].fd,numtowrite,NULL,0,
  1599.                startpos+nwritten);
  1600.   total_written += nwritten;
  1601.   
  1602.   /* Set up outbuf to return the correct return */
  1603.   outsize = set_message(outbuf,1,0,True);
  1604.   CVAL(outbuf,smb_com) = SMBwritec;
  1605.   SSVAL(outbuf,smb_vwv0,total_written);
  1606.  
  1607.   if (nwritten < numtowrite) {
  1608.     CVAL(outbuf,smb_rcls) = ERRHRD;
  1609.     SSVAL(outbuf,smb_err,ERRdiskfull);      
  1610.   }
  1611.  
  1612.   if (lp_syncalways(SNUM(cnum)) || write_through)
  1613.     sync_file(fnum);
  1614.  
  1615.   DEBUG(3,("%s writebraw2 fnum=%d cnum=%d start=%d num=%d wrote=%d\n",
  1616.        timestring(),fnum,cnum,startpos,numtowrite,total_written));
  1617.  
  1618.   /* we won't return a status if write through is not selected - this 
  1619.      follows what WfWg does */
  1620.   if (!write_through && total_written==tcount)
  1621.     return(-1);
  1622.  
  1623.   return(outsize);
  1624. }
  1625.  
  1626.  
  1627. /****************************************************************************
  1628.   reply to a writeunlock (core+)
  1629. ****************************************************************************/
  1630. int reply_writeunlock(char *inbuf,char *outbuf)
  1631. {
  1632.   int cnum,fnum;
  1633.   int nwritten = -1;
  1634.   int outsize = 0;
  1635.   int fd;
  1636.   char *data;
  1637.   uint32 numtowrite,startpos;
  1638.   int eclass;
  1639.   uint32 ecode;
  1640.   
  1641.   cnum = SVAL(inbuf,smb_tid);
  1642.   fnum = GETFNUM(inbuf,smb_vwv0);
  1643.  
  1644.   CHECK_FNUM(fnum,cnum);
  1645.   CHECK_WRITE(fnum);
  1646.   CHECK_ERROR(fnum);
  1647.  
  1648.   numtowrite = SVAL(inbuf,smb_vwv1);
  1649.   startpos = IVAL(inbuf,smb_vwv2);
  1650.   data = smb_buf(inbuf) + 3;
  1651.   
  1652.   fd = Files[fnum].fd;
  1653.  
  1654.   if (is_locked(fnum,cnum,numtowrite,startpos))
  1655.     return(ERROR(ERRDOS,ERRlock));
  1656.  
  1657.   seek_file(fnum,startpos);
  1658.  
  1659.   /* The special X/Open SMB protocol handling of
  1660.      zero length writes is *NOT* done for
  1661.      this call */
  1662.   if(numtowrite == 0)
  1663.     nwritten = 0;
  1664.   else
  1665.     nwritten = write_data(fd,data,numtowrite);
  1666.   
  1667.   if (lp_syncalways(SNUM(cnum)))
  1668.     sync_file(fnum);
  1669.  
  1670.   if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0))
  1671.     return(UNIXERROR(ERRDOS,ERRnoaccess));
  1672.  
  1673.   if(!do_unlock(fnum, cnum, numtowrite, startpos, &eclass, &ecode))
  1674.     return(ERROR(eclass,ecode));
  1675.  
  1676.   outsize = set_message(outbuf,1,0,True);
  1677.   
  1678.   SSVAL(outbuf,smb_vwv0,nwritten);
  1679.   
  1680.   DEBUG(3,("%s writeunlock fnum=%d cnum=%d num=%d wrote=%d\n",
  1681.        timestring(),fnum,cnum,numtowrite,nwritten));
  1682.   
  1683.   return(outsize);
  1684. }
  1685.  
  1686.  
  1687. /****************************************************************************
  1688.   reply to a write
  1689. ****************************************************************************/
  1690. int reply_write(char *inbuf,char *outbuf,int dum1,int dum2)
  1691. {
  1692.   int cnum,numtowrite,fnum;
  1693.   int nwritten = -1;
  1694.   int outsize = 0;
  1695.   int startpos;
  1696.   int fd;
  1697.   char *data;
  1698.  
  1699.   dum1 = dum2 = 0;
  1700.  
  1701.   
  1702.   cnum = SVAL(inbuf,smb_tid);
  1703.   fnum = GETFNUM(inbuf,smb_vwv0);
  1704.  
  1705.   CHECK_FNUM(fnum,cnum);
  1706.   CHECK_WRITE(fnum);
  1707.   CHECK_ERROR(fnum);
  1708.  
  1709.   numtowrite = SVAL(inbuf,smb_vwv1);
  1710.   startpos = IVAL(inbuf,smb_vwv2);
  1711.   data = smb_buf(inbuf) + 3;
  1712.   
  1713.   fd = Files[fnum].fd;
  1714.  
  1715.   if (is_locked(fnum,cnum,numtowrite,startpos))
  1716.     return(ERROR(ERRDOS,ERRlock));
  1717.  
  1718.   seek_file(fnum,startpos);
  1719.  
  1720.   /* X/Open SMB protocol says that if smb_vwv1 is
  1721.      zero then the file size should be extended or
  1722.      truncated to the size given in smb_vwv[2-3] */
  1723.   if(numtowrite == 0)
  1724.     nwritten = set_filelen(fd, startpos);
  1725.   else
  1726.     nwritten = write_data(fd,data,numtowrite);
  1727.   
  1728.   if (lp_syncalways(SNUM(cnum)))
  1729.     sync_file(fnum);
  1730.  
  1731.   if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0))
  1732.     return(UNIXERROR(ERRDOS,ERRnoaccess));
  1733.  
  1734.   outsize = set_message(outbuf,1,0,True);
  1735.   
  1736.   SSVAL(outbuf,smb_vwv0,nwritten);
  1737.  
  1738.   if (nwritten < numtowrite) {
  1739.     CVAL(outbuf,smb_rcls) = ERRHRD;
  1740.     SSVAL(outbuf,smb_err,ERRdiskfull);      
  1741.   }
  1742.   
  1743.   DEBUG(3,("%s write fnum=%d cnum=%d num=%d wrote=%d\n",timestring(),fnum,cnum,numtowrite,nwritten));
  1744.   
  1745.   return(outsize);
  1746. }
  1747.  
  1748.  
  1749. /****************************************************************************
  1750.   reply to a write and X
  1751. ****************************************************************************/
  1752. int reply_write_and_X(char *inbuf,char *outbuf,int length,int bufsize)
  1753. {
  1754.   int smb_com2 = CVAL(inbuf,smb_vwv0);
  1755.   int smb_off2 = SVAL(inbuf,smb_vwv1);
  1756.   int fnum = GETFNUM(inbuf,smb_vwv2);
  1757.   uint32 smb_offs = IVAL(inbuf,smb_vwv3);
  1758.   int smb_dsize = SVAL(inbuf,smb_vwv10);
  1759.   int smb_doff = SVAL(inbuf,smb_vwv11);
  1760.   BOOL write_through = BITSETW(inbuf+smb_vwv7,0);
  1761.   int cnum;
  1762.   int nwritten = -1;
  1763.   int outsize = 0;
  1764.   int fd;
  1765.   char *data;
  1766.  
  1767.   cnum = SVAL(inbuf,smb_tid);
  1768.  
  1769.   CHECK_FNUM(fnum,cnum);
  1770.   CHECK_WRITE(fnum);
  1771.   CHECK_ERROR(fnum);
  1772.  
  1773.   data = smb_base(inbuf) + smb_doff;
  1774.  
  1775.   fd = Files[fnum].fd;
  1776.  
  1777.   if (is_locked(fnum,cnum,smb_dsize,smb_offs))
  1778.     return(ERROR(ERRDOS,ERRlock));
  1779.  
  1780.   seek_file(fnum,smb_offs);
  1781.   
  1782.   /* X/Open SMB protocol says that, unlike SMBwrite
  1783.      if the length is zero then NO truncation is
  1784.      done, just a write of zero. To truncate a file,
  1785.      use SMBwrite. */
  1786.   if(smb_dsize == 0)
  1787.     nwritten = 0;
  1788.   else
  1789.     nwritten = write_data(fd,data,smb_dsize);
  1790.   
  1791.   if(((nwritten == 0) && (smb_dsize != 0))||(nwritten < 0))
  1792.     return(UNIXERROR(ERRDOS,ERRnoaccess));
  1793.  
  1794.   outsize = set_message(outbuf,6,0,True);
  1795.   
  1796.   CVAL(outbuf,smb_vwv0) = smb_com2;
  1797.   SSVAL(outbuf,smb_vwv1,(outsize+chain_size)-4);
  1798.   SSVAL(outbuf,smb_vwv2,nwritten);
  1799.   
  1800.   if (nwritten < smb_dsize) {
  1801.     CVAL(outbuf,smb_rcls) = ERRHRD;
  1802.     SSVAL(outbuf,smb_err,ERRdiskfull);      
  1803.   }
  1804.  
  1805.   DEBUG(3,("%s writeX fnum=%d cnum=%d num=%d wrote=%d\n",timestring(),fnum,cnum,smb_dsize,nwritten));
  1806.  
  1807.   chain_fnum = fnum;
  1808.  
  1809.   if (lp_syncalways(SNUM(cnum)) || write_through)
  1810.     sync_file(fnum);
  1811.  
  1812.   if (smb_com2 != 0xFF)
  1813.     outsize += chain_reply(smb_com2,inbuf,inbuf+smb_off2+4,
  1814.                outbuf,outbuf+outsize,
  1815.                length,bufsize);
  1816.   
  1817.   chain_fnum = -1;
  1818.   
  1819.   return(outsize);
  1820. }
  1821.  
  1822.  
  1823. /****************************************************************************
  1824.   reply to a lseek
  1825. ****************************************************************************/
  1826. int reply_lseek(char *inbuf,char *outbuf)
  1827. {
  1828.   int cnum,fnum;
  1829.   uint32 startpos;
  1830.   int32 res= -1;
  1831.   int mode,umode;
  1832.   int outsize = 0;
  1833.   
  1834.   cnum = SVAL(inbuf,smb_tid);
  1835.   fnum = GETFNUM(inbuf,smb_vwv0);
  1836.  
  1837.   CHECK_FNUM(fnum,cnum);
  1838.   CHECK_ERROR(fnum);
  1839.  
  1840.   mode = SVAL(inbuf,smb_vwv1) & 3;
  1841.   startpos = IVAL(inbuf,smb_vwv2);
  1842.  
  1843.   switch (mode & 3) 
  1844.     {
  1845.     case 0: umode = SEEK_SET; break;
  1846.     case 1: umode = SEEK_CUR; break;
  1847.     case 2: umode = SEEK_END; break;
  1848.     default:
  1849.       umode = SEEK_SET; break;
  1850.     }
  1851.   
  1852.   res = lseek(Files[fnum].fd,startpos,umode);
  1853.   Files[fnum].pos = res;
  1854.   
  1855.   outsize = set_message(outbuf,2,0,True);
  1856.   SIVALS(outbuf,smb_vwv0,res);
  1857.   
  1858.   DEBUG(3,("%s lseek fnum=%d cnum=%d ofs=%d mode=%d\n",timestring(),fnum,cnum,startpos,mode));
  1859.   
  1860.   return(outsize);
  1861. }
  1862.  
  1863.  
  1864. /****************************************************************************
  1865.   reply to a flush
  1866. ****************************************************************************/
  1867. int reply_flush(char *inbuf,char *outbuf)
  1868. {
  1869.   int cnum, fnum;
  1870.   int outsize = set_message(outbuf,0,0,True);
  1871.  
  1872.   cnum = SVAL(inbuf,smb_tid);
  1873.   fnum = GETFNUM(inbuf,smb_vwv0);
  1874.  
  1875.   if (fnum != 0xFFFF) {
  1876.     CHECK_FNUM(fnum,cnum);
  1877.     CHECK_ERROR(fnum);
  1878.   }
  1879.  
  1880.   if (fnum == 0xFFFF)
  1881.     {
  1882.       int i;
  1883.       for (i=0;i<MAX_OPEN_FILES;i++)
  1884.     if (OPEN_FNUM(i))
  1885.       sync_file(i);
  1886.     }
  1887.   else
  1888.     sync_file(fnum);
  1889.  
  1890.   DEBUG(3,("%s flush fnum=%d\n",timestring(),fnum));
  1891.   return(outsize);
  1892. }
  1893.  
  1894.  
  1895. /****************************************************************************
  1896.   reply to a exit
  1897. ****************************************************************************/
  1898. int reply_exit(char *inbuf,char *outbuf)
  1899. {
  1900.   int outsize = set_message(outbuf,0,0,True);
  1901.   DEBUG(3,("%s exit\n",timestring()));
  1902.   
  1903.   return(outsize);
  1904. }
  1905.  
  1906.  
  1907. /****************************************************************************
  1908.   reply to a close
  1909. ****************************************************************************/
  1910. int reply_close(char *inbuf,char *outbuf)
  1911. {
  1912.   int fnum,cnum;
  1913.   int outsize = 0;
  1914.   time_t mtime;
  1915.   int32 eclass = 0, err = 0;
  1916.  
  1917.   outsize = set_message(outbuf,0,0,True);
  1918.  
  1919.   cnum = SVAL(inbuf,smb_tid);
  1920.  
  1921.   fnum = GETFNUM(inbuf,smb_vwv0);
  1922.   CHECK_FNUM(fnum,cnum);
  1923.  
  1924.   if(HAS_CACHED_ERROR(fnum)) {
  1925.     eclass = Files[fnum].wbmpx_ptr->wr_errclass;
  1926.     err = Files[fnum].wbmpx_ptr->wr_error;
  1927.   }
  1928.  
  1929.   mtime = make_unix_date3(inbuf+smb_vwv1);
  1930.  
  1931.   close_file(fnum);
  1932.  
  1933.   /* try and set the date */
  1934.   set_filetime(Files[fnum].name,mtime);
  1935.  
  1936.   /* We have a cached error */
  1937.   if(eclass || err)
  1938.     return(ERROR(eclass,err));
  1939.  
  1940.   DEBUG(3,("%s close fd=%d fnum=%d cnum=%d (numopen=%d)\n",
  1941.        timestring(),Files[fnum].fd,fnum,cnum,
  1942.        Connections[cnum].num_files_open));
  1943.   
  1944.   return(outsize);
  1945. }
  1946.  
  1947.  
  1948. /****************************************************************************
  1949.   reply to a writeclose (Core+ protocol)
  1950. ****************************************************************************/
  1951. int reply_writeclose(char *inbuf,char *outbuf)
  1952. {
  1953.   int cnum,numtowrite,fnum;
  1954.   int nwritten = -1;
  1955.   int outsize = 0;
  1956.   int startpos;
  1957.   char *data;
  1958.   time_t mtime;
  1959.   
  1960.   cnum = SVAL(inbuf,smb_tid);
  1961.   fnum = GETFNUM(inbuf,smb_vwv0);
  1962.  
  1963.   CHECK_FNUM(fnum,cnum);
  1964.   CHECK_WRITE(fnum);
  1965.   CHECK_ERROR(fnum);
  1966.  
  1967.   numtowrite = SVAL(inbuf,smb_vwv1);
  1968.   startpos = IVAL(inbuf,smb_vwv2);
  1969.   mtime = make_unix_date3(inbuf+smb_vwv4);
  1970.   data = smb_buf(inbuf) + 1;
  1971.   
  1972.   if (is_locked(fnum,cnum,numtowrite,startpos))
  1973.     return(ERROR(ERRDOS,ERRlock));
  1974.       
  1975.   seek_file(fnum,startpos);
  1976.       
  1977.   nwritten = write_data(Files[fnum].fd,data,numtowrite);
  1978.  
  1979.   close_file(fnum);
  1980.  
  1981.   set_filetime(Files[fnum].name,mtime);
  1982.   
  1983.   DEBUG(3,("%s writeclose fnum=%d cnum=%d num=%d wrote=%d (numopen=%d)\n",
  1984.        timestring(),fnum,cnum,numtowrite,nwritten,
  1985.        Connections[cnum].num_files_open));
  1986.   
  1987.   if (nwritten <= 0)
  1988.     return(UNIXERROR(ERRDOS,ERRnoaccess));
  1989.   
  1990.   outsize = set_message(outbuf,1,0,True);
  1991.   
  1992.   SSVAL(outbuf,smb_vwv0,nwritten);
  1993.   return(outsize);
  1994. }
  1995.  
  1996.  
  1997. /****************************************************************************
  1998.   reply to a lock
  1999. ****************************************************************************/
  2000. int reply_lock(char *inbuf,char *outbuf)
  2001. {
  2002.   int fnum,cnum;
  2003.   int outsize = set_message(outbuf,0,0,True);
  2004.   uint32 count,offset;
  2005.   int eclass;
  2006.   uint32 ecode;
  2007.  
  2008.   cnum = SVAL(inbuf,smb_tid);
  2009.   fnum = GETFNUM(inbuf,smb_vwv0);
  2010.  
  2011.   CHECK_FNUM(fnum,cnum);
  2012.   CHECK_ERROR(fnum);
  2013.  
  2014.   count = IVAL(inbuf,smb_vwv1);
  2015.   offset = IVAL(inbuf,smb_vwv3);
  2016.  
  2017.   DEBUG(3,("%s lock fd=%d fnum=%d cnum=%d ofs=%d cnt=%d\n",timestring(),Files[fnum].fd,fnum,cnum,offset,count));
  2018.  
  2019.   if(!do_lock( fnum, cnum, count, offset, &eclass, &ecode))
  2020.     return (ERROR(eclass,ecode));
  2021.   
  2022.   return(outsize);
  2023. }
  2024.  
  2025.  
  2026. /****************************************************************************
  2027.   reply to a unlock
  2028. ****************************************************************************/
  2029. int reply_unlock(char *inbuf,char *outbuf)
  2030. {
  2031.   int fnum,cnum;
  2032.   int outsize = set_message(outbuf,0,0,True);
  2033.   uint32 count,offset;
  2034.   int eclass;
  2035.   uint32 ecode;
  2036.   
  2037.   cnum = SVAL(inbuf,smb_tid);
  2038.   fnum = GETFNUM(inbuf,smb_vwv0);
  2039.  
  2040.   CHECK_FNUM(fnum,cnum);
  2041.   CHECK_ERROR(fnum);
  2042.  
  2043.   count = IVAL(inbuf,smb_vwv1);
  2044.   offset = IVAL(inbuf,smb_vwv3);
  2045.  
  2046.   if(!do_unlock(fnum, cnum, count, offset, &eclass, &ecode))
  2047.     return (ERROR(eclass,ecode));
  2048.  
  2049.   DEBUG(3,("%s unlock fd=%d fnum=%d cnum=%d ofs=%d cnt=%d\n",timestring(),Files[fnum].fd,fnum,cnum,offset,count));
  2050.   
  2051.   return(outsize);
  2052. }
  2053.  
  2054.  
  2055. /****************************************************************************
  2056.   reply to a tdis
  2057. ****************************************************************************/
  2058. int reply_tdis(char *inbuf,char *outbuf)
  2059. {
  2060.   int cnum, uid;
  2061.   int outsize = set_message(outbuf,0,0,True);
  2062.   
  2063.   cnum = SVAL(inbuf,smb_tid);
  2064.   uid = SVAL(inbuf,smb_uid);
  2065.  
  2066.   Connections[cnum].used = False;
  2067.  
  2068.   close_cnum(cnum,uid);
  2069.   
  2070.   DEBUG(3,("%s tdis cnum=%d\n",timestring(),cnum));
  2071.  
  2072.   return outsize;
  2073. }
  2074.  
  2075.  
  2076.  
  2077. /****************************************************************************
  2078.   reply to a echo
  2079. ****************************************************************************/
  2080. int reply_echo(char *inbuf,char *outbuf)
  2081. {
  2082.   int cnum;
  2083.   int smb_reverb = SVAL(inbuf,smb_vwv0);
  2084.   int seq_num;
  2085.   int data_len = smb_buflen(inbuf);
  2086.   int outsize = set_message(outbuf,1,data_len,True);
  2087.  
  2088.   cnum = SVAL(inbuf,smb_tid);
  2089.  
  2090.   if (cnum != 0xFFFF && !OPEN_CNUM(cnum))
  2091.     {
  2092.       DEBUG(4,("Invalid cnum in echo (%d)\n",cnum));
  2093.       return(ERROR(ERRSRV,ERRinvnid));
  2094.     }
  2095.  
  2096.   /* copy any incoming data back out */
  2097.   if (data_len > 0)
  2098.     memcpy(smb_buf(outbuf),smb_buf(inbuf),data_len);
  2099.  
  2100.   if (smb_reverb > 100)
  2101.     {
  2102.       DEBUG(0,("large reverb (%d)?? Setting to 100\n",smb_reverb));
  2103.       smb_reverb = 100;
  2104.     }
  2105.  
  2106.   for (seq_num =1 ; seq_num <= smb_reverb ; seq_num++)
  2107.     {
  2108.       SSVAL(outbuf,smb_vwv0,seq_num);
  2109.  
  2110.       smb_setlen(outbuf,outsize - 4);
  2111.  
  2112.       send_smb(Client,outbuf);
  2113.     }
  2114.  
  2115.   DEBUG(3,("%s echo %d times cnum=%d\n",timestring(),smb_reverb,cnum));
  2116.  
  2117.   return -1;
  2118. }
  2119.  
  2120.  
  2121. /****************************************************************************
  2122.   reply to a printopen
  2123. ****************************************************************************/
  2124. int reply_printopen(char *inbuf,char *outbuf)
  2125. {
  2126.   pstring fname;
  2127.   pstring fname2;
  2128.   int cnum;
  2129.   int fnum = -1;
  2130.   int outsize = 0;
  2131.  
  2132.   *fname = *fname2 = 0;
  2133.  
  2134.   cnum = SVAL(inbuf,smb_tid);
  2135.  
  2136.   if (!CAN_PRINT(cnum))
  2137.     return(ERROR(ERRDOS,ERRnoaccess));
  2138.  
  2139.   {
  2140.     pstring s;
  2141.     char *p;
  2142.     StrnCpy(s,smb_buf(inbuf)+1,sizeof(pstring)-1);
  2143.     p = s;
  2144.     while (*p)
  2145.       {
  2146.     if (!(isalnum(*p) || strchr("._-",*p)))
  2147.       *p = 'X';
  2148.     p++;
  2149.       }
  2150.  
  2151.     if (strlen(s) > 10) s[10] = 0;
  2152.  
  2153.     sprintf(fname,"%s.XXXXXX",s);  
  2154.   }
  2155.  
  2156.   fnum = find_free_file();
  2157.   if (fnum < 0)
  2158.     return(ERROR(ERRSRV,ERRnofids));
  2159.  
  2160.   strcpy(fname2,(char *)mktemp(fname));
  2161.  
  2162.   if (!check_name(fname2,cnum))
  2163.     return(ERROR(ERRDOS,ERRnoaccess));
  2164.  
  2165.   open_file(fnum,cnum,fname2,O_WRONLY | O_CREAT | O_TRUNC,
  2166.         unix_mode(cnum,0));
  2167.  
  2168.   if (!Files[fnum].open)
  2169.     return(UNIXERROR(ERRDOS,ERRnoaccess));
  2170.  
  2171.   /* force it to be a print file */
  2172.   Files[fnum].print_file = True;
  2173.   
  2174.   outsize = set_message(outbuf,1,0,True);
  2175.   SSVAL(outbuf,smb_vwv0,fnum);
  2176.   
  2177.   DEBUG(3,("%s openprint %s fd=%d fnum=%d cnum=%d\n",timestring(),fname2,Files[fnum].fd,fnum,cnum));
  2178.   
  2179.   return(outsize);
  2180. }
  2181.  
  2182.  
  2183. /****************************************************************************
  2184.   reply to a printclose
  2185. ****************************************************************************/
  2186. int reply_printclose(char *inbuf,char *outbuf)
  2187. {
  2188.   int fnum,cnum;
  2189.   int outsize = set_message(outbuf,0,0,True);
  2190.   
  2191.   cnum = SVAL(inbuf,smb_tid);
  2192.   fnum = GETFNUM(inbuf,smb_vwv0);
  2193.  
  2194.   CHECK_FNUM(fnum,cnum);
  2195.   CHECK_ERROR(fnum);
  2196.  
  2197.   if (!CAN_PRINT(cnum))
  2198.     return(ERROR(ERRDOS,ERRnoaccess));
  2199.   
  2200.   close_file(fnum);
  2201.   
  2202.   DEBUG(3,("%s printclose fd=%d fnum=%d cnum=%d\n",timestring(),Files[fnum].fd,fnum,cnum));
  2203.   
  2204.   return(outsize);
  2205. }
  2206.  
  2207.  
  2208. /****************************************************************************
  2209.   reply to a printqueue
  2210. ****************************************************************************/
  2211. int reply_printqueue(char *inbuf,char *outbuf)
  2212. {
  2213.   int cnum, uid;
  2214.   int outsize = set_message(outbuf,2,3,True);
  2215.   int max_count = SVAL(inbuf,smb_vwv0);
  2216.   int start_index = SVAL(inbuf,smb_vwv1);
  2217.  
  2218.   cnum = SVAL(inbuf,smb_tid);
  2219.   uid = SVAL(inbuf,smb_uid);
  2220.  
  2221. /* allow checking the queue for anyone */
  2222. #if 0
  2223.   if (!CAN_PRINT(cnum))
  2224.     return(ERROR(ERRDOS,ERRnoaccess));
  2225. #endif
  2226.  
  2227.   SSVAL(outbuf,smb_vwv0,0);
  2228.   SSVAL(outbuf,smb_vwv1,0);
  2229.   CVAL(smb_buf(outbuf),0) = 1;
  2230.   SSVAL(smb_buf(outbuf),1,0);
  2231.   
  2232.   DEBUG(3,("%s printqueue cnum=%d start_index=%d max_count=%d\n",
  2233.     timestring(),cnum,start_index,max_count));
  2234.  
  2235.   if (!OPEN_CNUM(cnum) || !Connections[cnum].printer)
  2236.     {
  2237.       int i;
  2238.       cnum = -1;
  2239.  
  2240.       for (i=0;i<MAX_CONNECTIONS;i++)
  2241.     if (CAN_PRINT(i) && Connections[i].printer)
  2242.       cnum = i;
  2243.  
  2244.       if (cnum == -1)
  2245.     for (i=0;i<MAX_CONNECTIONS;i++)
  2246.       if (OPEN_CNUM(i))
  2247.         cnum = i;
  2248.  
  2249.       if (!OPEN_CNUM(cnum))
  2250.     return(ERROR(ERRSRV,ERRinvnid));
  2251.  
  2252.       DEBUG(5,("connection not open or not a printer, using cnum %d\n",cnum));
  2253.     }
  2254.  
  2255.   if (!become_user(cnum,uid))
  2256.     return(ERROR(ERRSRV,ERRinvnid));
  2257.  
  2258.   {
  2259.     print_queue_struct *queue = NULL;
  2260.     char *p = smb_buf(outbuf) + 3;
  2261.     int count = get_printqueue(SNUM(cnum),cnum,&queue,NULL);
  2262.     int num_to_get = ABS(max_count);
  2263.     int first = (max_count>0?start_index:start_index+max_count+1);
  2264.     int i;
  2265.  
  2266.     if (first >= count)
  2267.       num_to_get = 0;
  2268.     else
  2269.       num_to_get = MIN(num_to_get,count-first);
  2270.     
  2271.  
  2272.     for (i=first;i<first+num_to_get;i++)
  2273.       {
  2274.     put_dos_date2(p,0,queue[i].time);
  2275.     CVAL(p,4) = (queue[i].status==LPQ_PRINTING?2:3);
  2276.     SSVAL(p,5,queue[i].job);
  2277.     SIVAL(p,7,queue[i].size);
  2278.     CVAL(p,11) = 0;
  2279.     StrnCpy(p+12,queue[i].user,16);
  2280.     p += 28;
  2281.       }
  2282.  
  2283.     if (count > 0)
  2284.       {
  2285.     outsize = set_message(outbuf,2,28*count+3,False);      
  2286.     SSVAL(outbuf,smb_vwv0,count);
  2287.     SSVAL(outbuf,smb_vwv1,(max_count>0?first+count:first-1));
  2288.     CVAL(smb_buf(outbuf),0) = 1;
  2289.     SSVAL(smb_buf(outbuf),1,28*count);
  2290.       }
  2291.  
  2292.     if (queue) free(queue);
  2293.       
  2294.     DEBUG(3,("%d entries returned in queue\n",count));
  2295.   }
  2296.   
  2297.   return(outsize);
  2298. }
  2299.  
  2300.  
  2301. /****************************************************************************
  2302.   reply to a printwrite
  2303. ****************************************************************************/
  2304. int reply_printwrite(char *inbuf,char *outbuf)
  2305. {
  2306.   int cnum,numtowrite,fnum;
  2307.   int outsize = set_message(outbuf,0,0,True);
  2308.   char *data;
  2309.   
  2310.   cnum = SVAL(inbuf,smb_tid);
  2311.  
  2312.   if (!CAN_PRINT(cnum))
  2313.     return(ERROR(ERRDOS,ERRnoaccess));
  2314.  
  2315.   fnum = GETFNUM(inbuf,smb_vwv0);
  2316.  
  2317.   CHECK_FNUM(fnum,cnum);
  2318.   CHECK_WRITE(fnum);
  2319.   CHECK_ERROR(fnum);
  2320.  
  2321.   numtowrite = SVAL(smb_buf(inbuf),1);
  2322.   data = smb_buf(inbuf) + 3;
  2323.   
  2324.   if (write_data(Files[fnum].fd,data,numtowrite) != numtowrite)
  2325.     return(UNIXERROR(ERRDOS,ERRnoaccess));
  2326.   
  2327.   DEBUG(3,("%s printwrite fnum=%d cnum=%d num=%d\n",timestring(),fnum,cnum,numtowrite));
  2328.   
  2329.   return(outsize);
  2330. }
  2331.  
  2332.  
  2333. /****************************************************************************
  2334.   reply to a mkdir
  2335. ****************************************************************************/
  2336. int reply_mkdir(char *inbuf,char *outbuf)
  2337. {
  2338.   pstring directory;
  2339.   int cnum;
  2340.   int outsize,ret= -1;
  2341.   
  2342.   strcpy(directory,smb_buf(inbuf) + 1);
  2343.   cnum = SVAL(inbuf,smb_tid);
  2344.   unix_convert(directory,cnum);
  2345.   
  2346.   if (check_name(directory,cnum))
  2347.     ret = sys_mkdir(directory,unix_mode(cnum,aDIR));
  2348.   
  2349.   if (ret < 0)
  2350.     return(UNIXERROR(ERRDOS,ERRnoaccess));
  2351.   
  2352.   outsize = set_message(outbuf,0,0,True);
  2353.   
  2354.   DEBUG(3,("%s mkdir %s cnum=%d ret=%d\n",timestring(),directory,cnum,ret));
  2355.   
  2356.   return(outsize);
  2357. }
  2358.  
  2359.  
  2360. /****************************************************************************
  2361.   reply to a rmdir
  2362. ****************************************************************************/
  2363. int reply_rmdir(char *inbuf,char *outbuf)
  2364. {
  2365.   pstring directory;
  2366.   int cnum;
  2367.   int outsize = 0;
  2368.   BOOL ok = False;
  2369.   
  2370.   cnum = SVAL(inbuf,smb_tid);
  2371.   strcpy(directory,smb_buf(inbuf) + 1);
  2372.   unix_convert(directory,cnum);
  2373.   
  2374.   if (check_name(directory,cnum))
  2375.     {
  2376.       dptr_closepath(directory,SVAL(inbuf,smb_pid));
  2377.       ok = (sys_rmdir(directory) == 0);
  2378.       if (!ok)
  2379.     DEBUG(3,("couldn't remove directory %s : %s\n",
  2380.          directory,strerror(errno)));
  2381.     }
  2382.   
  2383.   if (!ok)
  2384.     return(UNIXERROR(ERRDOS,ERRbadpath));
  2385.   
  2386.   outsize = set_message(outbuf,0,0,True);
  2387.   
  2388.   DEBUG(3,("%s rmdir %s\n",timestring(),directory));
  2389.   
  2390.   return(outsize);
  2391. }
  2392.  
  2393.  
  2394. /*******************************************************************
  2395. resolve wildcards in a filename rename
  2396. ********************************************************************/
  2397. static BOOL resolve_wildcards(char *name1,char *name2)
  2398. {
  2399.   fstring root1,root2;
  2400.   fstring ext1,ext2;
  2401.   char *p,*p2;
  2402.  
  2403.   name1 = strrchr(name1,'/');
  2404.   name2 = strrchr(name2,'/');
  2405.  
  2406.   if (!name1 || !name2) return(False);
  2407.   
  2408.   strcpy(root1,name1);
  2409.   strcpy(root2,name2);
  2410.   p = strrchr(root1,'.');
  2411.   if (p) {
  2412.     *p = 0;
  2413.     strcpy(ext1,p+1);
  2414.   } else {
  2415.     strcpy(ext1,"");    
  2416.   }
  2417.   p = strrchr(root2,'.');
  2418.   if (p) {
  2419.     *p = 0;
  2420.     strcpy(ext2,p+1);
  2421.   } else {
  2422.     strcpy(ext2,"");    
  2423.   }
  2424.  
  2425.   p = root1;
  2426.   p2 = root2;
  2427.   while (*p2) {
  2428.     if (*p2 == '?') {
  2429.       *p2 = *p;
  2430.       p2++;
  2431.     } else {
  2432.       p2++;
  2433.     }
  2434.     if (*p) p++;
  2435.   }
  2436.  
  2437.   p = ext1;
  2438.   p2 = ext2;
  2439.   while (*p2) {
  2440.     if (*p2 == '?') {
  2441.       *p2 = *p;
  2442.       p2++;
  2443.     } else {
  2444.       p2++;
  2445.     }
  2446.     if (*p) p++;
  2447.   }
  2448.  
  2449.   strcpy(name2,root2);
  2450.   if (ext2[0]) {
  2451.     strcat(name2,".");
  2452.     strcat(name2,ext2);
  2453.   }
  2454.  
  2455.   return(True);
  2456. }
  2457.  
  2458. /*******************************************************************
  2459. check if a user is allowed to rename a file
  2460. ********************************************************************/
  2461. static BOOL can_rename(char *fname,int cnum)
  2462. {
  2463.   struct stat sbuf;
  2464.  
  2465.   if (!CAN_WRITE(cnum)) return(False);
  2466.  
  2467.   if (sys_lstat(fname,&sbuf) != 0) return(False);
  2468.   if (!check_file_sharing(cnum,fname)) return(False);
  2469.  
  2470.   return(True);
  2471. }
  2472.  
  2473. /****************************************************************************
  2474.   reply to a mv
  2475. ****************************************************************************/
  2476. int reply_mv(char *inbuf,char *outbuf)
  2477. {
  2478.   int outsize = 0;
  2479.   pstring name;
  2480.   int cnum;
  2481.   pstring directory;
  2482.   pstring mask,newname;
  2483.   char *p;
  2484.   int count=0;
  2485.   int error = ERRnoaccess;
  2486.   BOOL has_wild;
  2487.   BOOL exists=False;
  2488.  
  2489.   *directory = *mask = 0;
  2490.  
  2491.   cnum = SVAL(inbuf,smb_tid);
  2492.   
  2493.   strcpy(name,smb_buf(inbuf) + 1);
  2494.   strcpy(newname,smb_buf(inbuf) + 3 + strlen(name));
  2495.    
  2496.   DEBUG(3,("reply_mv : %s -> %s\n",name,newname));
  2497.    
  2498.   unix_convert(name,cnum);
  2499.   unix_convert(newname,cnum);
  2500.  
  2501.   p = strrchr(name,'/');
  2502.   if (!p) {
  2503.     strcpy(directory,"./");
  2504.     strcpy(mask,name);
  2505.   } else {
  2506.     *p = 0;
  2507.     strcpy(directory,name);
  2508.     strcpy(mask,p+1);
  2509.   }
  2510.  
  2511.   if (is_mangled(mask))
  2512.     check_mangled_stack(mask);
  2513.  
  2514.   has_wild = strchr(mask,'*') || strchr(mask,'?');
  2515.  
  2516.   if (!has_wild) {
  2517.     strcat(directory,"/");
  2518.     strcat(directory,mask);
  2519.     if (resolve_wildcards(directory,newname) && 
  2520.     can_rename(directory,cnum) && 
  2521.     !file_exist(newname,NULL) &&
  2522.     !sys_rename(directory,newname)) count++;
  2523.     if (!count) exists = file_exist(directory,NULL);
  2524.     if (!count && exists && file_exist(newname,NULL)) {
  2525.       exists = True;
  2526.       error = 183;
  2527.     }
  2528.   } else {
  2529.     void *dirptr = NULL;
  2530.     char *dname;
  2531.     pstring destname;
  2532.  
  2533.     if (check_name(directory,cnum))
  2534.       dirptr = OpenDir(directory);
  2535.  
  2536.     if (dirptr)
  2537.       {
  2538.     error = ERRbadfile;
  2539.  
  2540.     if (strequal(mask,"????????.???"))
  2541.       strcpy(mask,"*");
  2542.  
  2543.     while ((dname = ReadDirName(dirptr)))
  2544.       {
  2545.         pstring fname;
  2546.         strcpy(fname,dname);
  2547.         
  2548.         if(!mask_match(fname, mask, case_sensitive, False)) continue;
  2549.  
  2550.         error = ERRnoaccess;
  2551.         sprintf(fname,"%s/%s",directory,dname);
  2552.         if (!can_rename(fname,cnum)) continue;
  2553.         strcpy(destname,newname);
  2554.  
  2555.         if (!resolve_wildcards(fname,destname)) continue;
  2556.  
  2557.         if (file_exist(destname,NULL)) {
  2558.           error = 183;
  2559.           continue;
  2560.         }
  2561.         if (!sys_rename(fname,destname)) count++;
  2562.         DEBUG(3,("reply_mv : doing rename on %s -> %s\n",fname,destname));
  2563.       }
  2564.     CloseDir(dirptr);
  2565.       }
  2566.   }
  2567.   
  2568.   if (count == 0) {
  2569.     if (exists)
  2570.       return(ERROR(ERRDOS,error));
  2571.     else
  2572.       return(UNIXERROR(ERRDOS,error));
  2573.   }
  2574.   
  2575.   outsize = set_message(outbuf,0,0,True);
  2576.   
  2577.   return(outsize);
  2578. }
  2579.  
  2580. /*******************************************************************
  2581.   copy a file as part of a reply_copy
  2582.   ******************************************************************/
  2583. static BOOL copy_file(char *src,char *dest1,int cnum,int ofun,
  2584.               int count,BOOL target_is_directory)
  2585. {
  2586.   int Access,action;
  2587.   struct stat st;
  2588.   int ret;
  2589.   int fnum1,fnum2;
  2590.   pstring dest;
  2591.   
  2592.   strcpy(dest,dest1);
  2593.   if (target_is_directory) {
  2594.     char *p = strrchr(src,'/');
  2595.     if (p) 
  2596.       p++;
  2597.     else
  2598.       p = src;
  2599.     strcat(dest,"/");
  2600.     strcat(dest,p);
  2601.   }
  2602.  
  2603.   if (!file_exist(src,&st)) return(False);
  2604.  
  2605.   fnum1 = find_free_file();
  2606.   if (fnum1<0) return(False);
  2607.   open_file_shared(fnum1,cnum,src,(DENY_NONE<<4),
  2608.            1,0,&Access,&action);
  2609.  
  2610.   if (!Files[fnum1].open) return(False);
  2611.  
  2612.   if (!target_is_directory && count)
  2613.     ofun = 1;
  2614.  
  2615.   fnum2 = find_free_file();
  2616.   if (fnum2<0) {
  2617.     close_file(fnum1);
  2618.     return(False);
  2619.   }
  2620.   open_file_shared(fnum2,cnum,dest,(DENY_NONE<<4)|1,
  2621.            ofun,st.st_mode,&Access,&action);
  2622.  
  2623.   if (!Files[fnum2].open) {
  2624.     close_file(fnum1);
  2625.     return(False);
  2626.   }
  2627.  
  2628.   if ((ofun&3) == 1) {
  2629.     lseek(Files[fnum2].fd,0,SEEK_END);
  2630.   }
  2631.   
  2632.   if (st.st_size)
  2633.     ret = transfer_file(Files[fnum1].fd,Files[fnum2].fd,st.st_size,NULL,0,0);
  2634.  
  2635.   close_file(fnum1);
  2636.   close_file(fnum2);
  2637.  
  2638.   return(ret == st.st_size);
  2639. }
  2640.  
  2641.  
  2642.  
  2643. /****************************************************************************
  2644.   reply to a file copy.
  2645.   ****************************************************************************/
  2646. int reply_copy(char *inbuf,char *outbuf)
  2647. {
  2648.   int outsize = 0;
  2649.   pstring name;
  2650.   int cnum;
  2651.   pstring directory;
  2652.   pstring mask,newname;
  2653.   char *p;
  2654.   int count=0;
  2655.   int error = ERRnoaccess;
  2656.   BOOL has_wild;
  2657.   BOOL exists=False;
  2658.   int tid2 = SVAL(inbuf,smb_vwv0);
  2659.   int ofun = SVAL(inbuf,smb_vwv1);
  2660.   int flags = SVAL(inbuf,smb_vwv2);
  2661.   BOOL target_is_directory=False;
  2662.  
  2663.   *directory = *mask = 0;
  2664.  
  2665.   cnum = SVAL(inbuf,smb_tid);
  2666.   
  2667.   strcpy(name,smb_buf(inbuf));
  2668.   strcpy(newname,smb_buf(inbuf) + 1 + strlen(name));
  2669.    
  2670.   DEBUG(3,("reply_copy : %s -> %s\n",name,newname));
  2671.    
  2672.   if (tid2 != cnum) {
  2673.     /* can't currently handle inter share copies XXXX */
  2674.     DEBUG(3,("Rejecting inter-share copy\n"));
  2675.     return(ERROR(ERRSRV,ERRinvdevice));
  2676.   }
  2677.  
  2678.   unix_convert(name,cnum);
  2679.   unix_convert(newname,cnum);
  2680.  
  2681.   target_is_directory = directory_exist(newname,NULL);
  2682.  
  2683.   if ((flags&1) && target_is_directory) {
  2684.     return(ERROR(ERRDOS,ERRbadfile));
  2685.   }
  2686.  
  2687.   if ((flags&2) && !target_is_directory) {
  2688.     return(ERROR(ERRDOS,ERRbadpath));
  2689.   }
  2690.  
  2691.   if ((flags&(1<<5)) && directory_exist(name,NULL)) {
  2692.     /* wants a tree copy! XXXX */
  2693.     DEBUG(3,("Rejecting tree copy\n"));
  2694.     return(ERROR(ERRSRV,ERRerror));    
  2695.   }
  2696.  
  2697.   p = strrchr(name,'/');
  2698.   if (!p) {
  2699.     strcpy(directory,"./");
  2700.     strcpy(mask,name);
  2701.   } else {
  2702.     *p = 0;
  2703.     strcpy(directory,name);
  2704.     strcpy(mask,p+1);
  2705.   }
  2706.  
  2707.   if (is_mangled(mask))
  2708.     check_mangled_stack(mask);
  2709.  
  2710.   has_wild = strchr(mask,'*') || strchr(mask,'?');
  2711.  
  2712.   if (!has_wild) {
  2713.     strcat(directory,"/");
  2714.     strcat(directory,mask);
  2715.     if (resolve_wildcards(directory,newname) && 
  2716.     copy_file(directory,newname,cnum,ofun,
  2717.           count,target_is_directory)) count++;
  2718.     if (!count) exists = file_exist(directory,NULL);
  2719.   } else {
  2720.     void *dirptr = NULL;
  2721.     char *dname;
  2722.     pstring destname;
  2723.  
  2724.     if (check_name(directory,cnum))
  2725.       dirptr = OpenDir(directory);
  2726.  
  2727.     if (dirptr)
  2728.       {
  2729.     error = ERRbadfile;
  2730.  
  2731.     if (strequal(mask,"????????.???"))
  2732.       strcpy(mask,"*");
  2733.  
  2734.     while ((dname = ReadDirName(dirptr)))
  2735.       {
  2736.         pstring fname;
  2737.         strcpy(fname,dname);
  2738.         
  2739.         if(!mask_match(fname, mask, case_sensitive, False)) continue;
  2740.  
  2741.         error = ERRnoaccess;
  2742.         sprintf(fname,"%s/%s",directory,dname);
  2743.         strcpy(destname,newname);
  2744.         if (resolve_wildcards(fname,destname) && 
  2745.         copy_file(directory,newname,cnum,ofun,
  2746.               count,target_is_directory)) count++;
  2747.         DEBUG(3,("reply_copy : doing copy on %s -> %s\n",fname,destname));
  2748.       }
  2749.     CloseDir(dirptr);
  2750.       }
  2751.   }
  2752.   
  2753.   if (count == 0) {
  2754.     if (exists)
  2755.       return(ERROR(ERRDOS,error));
  2756.     else
  2757.       return(UNIXERROR(ERRDOS,error));
  2758.   }
  2759.   
  2760.   outsize = set_message(outbuf,1,0,True);
  2761.   SSVAL(outbuf,smb_vwv0,count);
  2762.  
  2763.   return(outsize);
  2764. }
  2765.  
  2766.  
  2767.  
  2768. /****************************************************************************
  2769.   reply to a setdir
  2770. ****************************************************************************/
  2771. int reply_setdir(char *inbuf,char *outbuf)
  2772. {
  2773.   int cnum,snum;
  2774.   int outsize = 0;
  2775.   BOOL ok = False;
  2776.   pstring newdir;
  2777.   
  2778.   cnum = SVAL(inbuf,smb_tid);
  2779.   
  2780.   snum = Connections[cnum].service;
  2781.   if (!CAN_SETDIR(snum))
  2782.     return(ERROR(ERRDOS,ERRnoaccess));
  2783.   
  2784.   strcpy(newdir,smb_buf(inbuf) + 1);
  2785.   strlower(newdir);
  2786.   
  2787.   if (strlen(newdir) == 0)
  2788.     ok = True;
  2789.   else
  2790.     {
  2791.       ok = directory_exist(newdir,NULL);
  2792.       if (ok)
  2793.     string_set(&Connections[cnum].connectpath,newdir);
  2794.     }
  2795.   
  2796.   if (!ok)
  2797.     return(ERROR(ERRDOS,ERRbadpath));
  2798.   
  2799.   outsize = set_message(outbuf,0,0,True);
  2800.   CVAL(outbuf,smb_reh) = CVAL(inbuf,smb_reh);
  2801.   
  2802.   DEBUG(3,("%s setdir %s cnum=%d\n",timestring(),newdir,cnum));
  2803.   
  2804.   return(outsize);
  2805. }
  2806.  
  2807.  
  2808. /****************************************************************************
  2809.   reply to a lockingX request
  2810. ****************************************************************************/
  2811. int reply_lockingX(char *inbuf,char *outbuf,int length,int bufsize)
  2812. {
  2813.   int smb_com2 = CVAL(inbuf,smb_vwv0);
  2814.   int smb_off2 = SVAL(inbuf,smb_vwv1);
  2815.   int fnum = GETFNUM(inbuf,smb_vwv2);
  2816.   uint16 locktype = SVAL(inbuf,smb_vwv3);
  2817.   uint16 num_ulocks = SVAL(inbuf,smb_vwv6);
  2818.   uint16 num_locks = SVAL(inbuf,smb_vwv7);
  2819.   uint32 count, offset;
  2820.  
  2821.   int cnum;
  2822.   int i;
  2823.   char *data;
  2824.   uint32 ecode=0, dummy2;
  2825.   int outsize, eclass=0, dummy1;
  2826.  
  2827.   cnum = SVAL(inbuf,smb_tid);
  2828.  
  2829.   CHECK_FNUM(fnum,cnum);
  2830.   CHECK_ERROR(fnum);
  2831.  
  2832.   data = smb_buf(inbuf);
  2833.   /* Data now points at the beginning of the list
  2834.      of smb_unlkrng structs */
  2835.   for(i = 0; i < (int)num_ulocks; i++) {
  2836.     count = IVAL(data,SMB_LKLEN_OFFSET(i));
  2837.     offset = IVAL(data,SMB_LKOFF_OFFSET(i));
  2838.     if(!do_unlock(fnum,cnum,count,offset,&eclass, &ecode))
  2839.       return ERROR(eclass,ecode);
  2840.   }
  2841.  
  2842.   /* Now do any requested locks */
  2843.   data += 10*num_ulocks;
  2844.   /* Data now points at the beginning of the list
  2845.      of smb_lkrng structs */
  2846.   for(i = 0; i < (int)num_locks; i++) {
  2847.     count = IVAL(data,SMB_LKLEN_OFFSET(i)); 
  2848.     offset = IVAL(data,SMB_LKOFF_OFFSET(i)); 
  2849.     if(!do_lock(fnum,cnum,count,offset, &eclass, &ecode))
  2850.       break;
  2851.   }
  2852.  
  2853.   /* If any of the above locks failed, then we must unlock
  2854.      all of the previous locks (X/Open spec). */
  2855.   if(i != num_locks && num_locks != 0) {
  2856.     for(; i >= 0; i--) {
  2857.       count = IVAL(data,SMB_LKLEN_OFFSET(i));  
  2858.       offset = IVAL(data,SMB_LKOFF_OFFSET(i)); 
  2859.       do_unlock(fnum,cnum,count,offset,&dummy1,&dummy2);
  2860.     }
  2861.     return ERROR(eclass,ecode);
  2862.   }
  2863.  
  2864.   outsize = set_message(outbuf,2,0,True);
  2865.   
  2866.   CVAL(outbuf,smb_vwv0) = smb_com2;
  2867.   SSVAL(outbuf,smb_vwv1,(outsize+chain_size)-4);
  2868.   
  2869.   DEBUG(3,("%s lockingX fnum=%d cnum=%d type=%d num_locks=%d num_ulocks=%d\n",
  2870.     timestring(),fnum,cnum,locktype,num_locks,num_ulocks));
  2871.  
  2872.   chain_fnum = fnum;
  2873.  
  2874.   if (smb_com2 != 0xFF)
  2875.     outsize += chain_reply(smb_com2,inbuf,inbuf+smb_off2+4,
  2876.                outbuf,outbuf+outsize,
  2877.                length,bufsize);
  2878.   
  2879.   chain_fnum = -1;
  2880.   
  2881.   return(outsize);
  2882. }
  2883.  
  2884.  
  2885. /****************************************************************************
  2886.   reply to a SMBreadbmpx (read block multiplex) request
  2887. ****************************************************************************/
  2888. int reply_readbmpx(char *inbuf,char *outbuf,int length,int bufsize)
  2889. {
  2890.   int cnum,fnum;
  2891.   int nread = -1;
  2892.   int total_read;
  2893.   char *data;
  2894.   int32 startpos;
  2895.   int outsize, mincount, maxcount;
  2896.   int max_per_packet;
  2897.   int tcount;
  2898.   int pad;
  2899.  
  2900.   /* this function doesn't seem to work - disable by default */
  2901.   if (!lp_readbmpx())
  2902.     return(ERROR(ERRSRV,ERRuseSTD));
  2903.  
  2904.   outsize = set_message(outbuf,8,0,True);
  2905.  
  2906.   cnum = SVAL(inbuf,smb_tid);
  2907.   fnum = GETFNUM(inbuf,smb_vwv0);
  2908.  
  2909.   CHECK_FNUM(fnum,cnum);
  2910.   CHECK_READ(fnum);
  2911.   CHECK_ERROR(fnum);
  2912.  
  2913.   startpos = IVAL(inbuf,smb_vwv1);
  2914.   maxcount = SVAL(inbuf,smb_vwv3);
  2915.   mincount = SVAL(inbuf,smb_vwv4);
  2916.  
  2917.   data = smb_buf(outbuf);
  2918.   pad = ((int)data)%4;
  2919.   if (pad) pad = 4 - pad;
  2920.   data += pad;
  2921.  
  2922.   max_per_packet = bufsize-(outsize+pad);
  2923.   tcount = maxcount;
  2924.   total_read = 0;
  2925.  
  2926.   if (is_locked(fnum,cnum,maxcount,startpos))
  2927.     return(ERROR(ERRDOS,ERRlock));
  2928.     
  2929.   do
  2930.     {
  2931.       int N = MIN(max_per_packet,tcount-total_read);
  2932.   
  2933.       nread = read_file(fnum,data,startpos,N,N,-1,False);
  2934.  
  2935.       if (nread <= 0) nread = 0;
  2936.  
  2937.       if (nread < N)
  2938.     tcount = total_read + nread;
  2939.  
  2940.       set_message(outbuf,8,nread,False);
  2941.       SIVAL(outbuf,smb_vwv0,startpos);
  2942.       SSVAL(outbuf,smb_vwv2,tcount);
  2943.       SSVAL(outbuf,smb_vwv6,nread);
  2944.       SSVAL(outbuf,smb_vwv7,smb_offset(data,outbuf));
  2945.  
  2946.       send_smb(Client,outbuf);
  2947.  
  2948.       total_read += nread;
  2949.       startpos += nread;
  2950.     }
  2951.   while (total_read < tcount);
  2952.  
  2953.   return(-1);
  2954. }
  2955.  
  2956.  
  2957. /****************************************************************************
  2958.   reply to a SMBwritebmpx (write block multiplex primary) request
  2959. ****************************************************************************/
  2960. int reply_writebmpx(char *inbuf,char *outbuf)
  2961. {
  2962.   int cnum,numtowrite,fnum;
  2963.   int nwritten = -1;
  2964.   int outsize = 0;
  2965.   int32 startpos;
  2966.   int tcount, write_through, smb_doff;
  2967.   int fd;
  2968.   char *data;
  2969.   
  2970.   cnum = SVAL(inbuf,smb_tid);
  2971.   fnum = GETFNUM(inbuf,smb_vwv0);
  2972.  
  2973.   CHECK_FNUM(fnum,cnum);
  2974.   CHECK_WRITE(fnum);
  2975.   CHECK_ERROR(fnum);
  2976.  
  2977.   tcount = SVAL(inbuf,smb_vwv1);
  2978.   startpos = IVAL(inbuf,smb_vwv3);
  2979.   write_through = BITSETW(inbuf+smb_vwv7,0);
  2980.   numtowrite = SVAL(inbuf,smb_vwv10);
  2981.   smb_doff = SVAL(inbuf,smb_vwv11);
  2982.  
  2983.   data = smb_base(inbuf) + smb_doff;
  2984.  
  2985.   /* If this fails we need to send an SMBwriteC response,
  2986.      not an SMBwritebmpx - set this up now so we don't forget */
  2987.   CVAL(outbuf,smb_com) = SMBwritec;
  2988.  
  2989.   fd = Files[fnum].fd;
  2990.  
  2991.   if (is_locked(fnum,cnum,tcount,startpos))
  2992.     return(ERROR(ERRDOS,ERRlock));
  2993.  
  2994.   seek_file(fnum,startpos);
  2995.   nwritten = write_data(fd,data,numtowrite);
  2996.  
  2997.   if(lp_syncalways(SNUM(cnum)) || write_through)
  2998.     sync_file(fnum);
  2999.   
  3000.   if(nwritten < numtowrite)
  3001.     return(UNIXERROR(ERRHRD,ERRdiskfull));
  3002.  
  3003.   /* If the maximum to be written to this file
  3004.      is greater than what we just wrote then set
  3005.      up a secondary struct to be attached to this
  3006.      fd, we will use this to cache error messages etc. */
  3007.   if(tcount > nwritten) 
  3008.     {
  3009.       write_bmpx_struct *wbms;
  3010.       if(Files[fnum].wbmpx_ptr != NULL)
  3011.     wbms = Files[fnum].wbmpx_ptr; /* Use an existing struct */
  3012.       else
  3013.     wbms = (write_bmpx_struct *)malloc(sizeof(write_bmpx_struct));
  3014.       if(!wbms)
  3015.     {
  3016.       DEBUG(0,("Out of memory in reply_readmpx\n"));
  3017.       return(ERROR(ERRSRV,ERRnoresource));
  3018.     }
  3019.       wbms->wr_mode = write_through;
  3020.       wbms->wr_discard = False; /* No errors yet */
  3021.       wbms->wr_total_written = nwritten;
  3022.       wbms->wr_errclass = 0;
  3023.       wbms->wr_error = 0;
  3024.       Files[fnum].wbmpx_ptr = wbms;
  3025.     }
  3026.  
  3027.   /* We are returning successfully, set the message type back to
  3028.      SMBwritebmpx */
  3029.   CVAL(outbuf,smb_com) = SMBwriteBmpx;
  3030.   
  3031.   outsize = set_message(outbuf,1,0,True);
  3032.   
  3033.   SSVALS(outbuf,smb_vwv0,-1); /* We don't support smb_remaining */
  3034.   
  3035.   DEBUG(3,("%s writebmpx fnum=%d cnum=%d num=%d wrote=%d\n",
  3036.     timestring(),fnum,cnum,numtowrite,nwritten));
  3037.   
  3038.   if (write_through && tcount==nwritten) {
  3039.     /* we need to send both a primary and a secondary response */
  3040.     smb_setlen(outbuf,outsize - 4);
  3041.     send_smb(Client,outbuf);
  3042.  
  3043.     /* now the secondary */
  3044.     outsize = set_message(outbuf,1,0,True);
  3045.     CVAL(outbuf,smb_com) = SMBwritec;
  3046.     SSVAL(outbuf,smb_vwv0,nwritten);
  3047.   }
  3048.  
  3049.   return(outsize);
  3050. }
  3051.  
  3052.  
  3053. /****************************************************************************
  3054.   reply to a SMBwritebs (write block multiplex secondary) request
  3055. ****************************************************************************/
  3056. int reply_writebs(char *inbuf,char *outbuf)
  3057. {
  3058.   int cnum,numtowrite,fnum;
  3059.   int nwritten = -1;
  3060.   int outsize = 0;
  3061.   int32 startpos;
  3062.   int tcount, write_through, smb_doff;
  3063.   int fd;
  3064.   char *data;
  3065.   write_bmpx_struct *wbms;
  3066.   BOOL send_response = False;
  3067.   
  3068.   cnum = SVAL(inbuf,smb_tid);
  3069.   fnum = GETFNUM(inbuf,smb_vwv0);
  3070.   CHECK_FNUM(fnum,cnum);
  3071.   CHECK_WRITE(fnum);
  3072.  
  3073.   tcount = SVAL(inbuf,smb_vwv1);
  3074.   startpos = IVAL(inbuf,smb_vwv2);
  3075.   numtowrite = SVAL(inbuf,smb_vwv6);
  3076.   smb_doff = SVAL(inbuf,smb_vwv7);
  3077.  
  3078.   data = smb_base(inbuf) + smb_doff;
  3079.  
  3080.   /* We need to send an SMBwriteC response, not an SMBwritebs */
  3081.   CVAL(outbuf,smb_com) = SMBwritec;
  3082.  
  3083.   /* This fd should have an auxiliary struct attached,
  3084.      check that it does */
  3085.   wbms = Files[fnum].wbmpx_ptr;
  3086.   if(!wbms) return(-1);
  3087.  
  3088.   /* If write through is set we can return errors, else we must
  3089.      cache them */
  3090.   write_through = wbms->wr_mode;
  3091.  
  3092.   /* Check for an earlier error */
  3093.   if(wbms->wr_discard)
  3094.     return -1; /* Just discard the packet */
  3095.  
  3096.   fd = Files[fnum].fd;
  3097.  
  3098.   seek_file(fnum,startpos);
  3099.   nwritten = write_data(fd,data,numtowrite);
  3100.  
  3101.   if(lp_syncalways(SNUM(cnum)) || write_through)
  3102.     sync_file(fnum);
  3103.   
  3104.   if (nwritten < numtowrite)
  3105.     {
  3106.       if(write_through)    {
  3107.     /* We are returning an error - we can delete the aux struct */
  3108.     if (wbms) free((char *)wbms);
  3109.     Files[fnum].wbmpx_ptr = NULL;
  3110.     return(ERROR(ERRHRD,ERRdiskfull));
  3111.       }
  3112.       return(CACHE_ERROR(wbms,ERRHRD,ERRdiskfull));
  3113.     }
  3114.  
  3115.   /* Increment the total written, if this matches tcount
  3116.      we can discard the auxiliary struct (hurrah !) and return a writeC */
  3117.   wbms->wr_total_written += nwritten;
  3118.   if(wbms->wr_total_written >= tcount)
  3119.     {
  3120.       if (write_through) {
  3121.     outsize = set_message(outbuf,1,0,True);
  3122.     SSVAL(outbuf,smb_vwv0,wbms->wr_total_written);    
  3123.     send_response = True;
  3124.       }
  3125.  
  3126.       free((char *)wbms);
  3127.       Files[fnum].wbmpx_ptr = NULL;
  3128.     }
  3129.  
  3130.   if(send_response)
  3131.     return(outsize);
  3132.  
  3133.   return(-1);
  3134. }
  3135.  
  3136.  
  3137. /****************************************************************************
  3138.   reply to a SMBsetattrE
  3139. ****************************************************************************/
  3140. int reply_setattrE(char *inbuf,char *outbuf)
  3141. {
  3142.   int cnum,fnum;
  3143.   struct utimbuf unix_times;
  3144.   int outsize = 0;
  3145.  
  3146.   outsize = set_message(outbuf,0,0,True);
  3147.  
  3148.   cnum = SVAL(inbuf,smb_tid);
  3149.   fnum = GETFNUM(inbuf,smb_vwv0);
  3150.  
  3151.   CHECK_FNUM(fnum,cnum);
  3152.   CHECK_ERROR(fnum);
  3153.  
  3154.   /* Convert the DOS times into unix times. Ignore create
  3155.      time as UNIX can't set this.
  3156.      */
  3157.   unix_times.actime = make_unix_date2(inbuf+smb_vwv3);
  3158.   unix_times.modtime = make_unix_date2(inbuf+smb_vwv5);
  3159.   
  3160.   /* Set the date on this file */
  3161.   if(sys_utime(Files[fnum].name, &unix_times))
  3162.     return(ERROR(ERRDOS,ERRnoaccess));
  3163.   
  3164.   DEBUG(3,("%s reply_setattrE fnum=%d cnum=%d\n",timestring(),fnum,cnum));
  3165.  
  3166.   return(outsize);
  3167. }
  3168.  
  3169.  
  3170. /****************************************************************************
  3171.   reply to a SMBgetattrE
  3172. ****************************************************************************/
  3173. int reply_getattrE(char *inbuf,char *outbuf)
  3174. {
  3175.   int cnum,fnum;
  3176.   struct stat sbuf;
  3177.   int outsize = 0;
  3178.   int mode;
  3179.  
  3180.   outsize = set_message(outbuf,11,0,True);
  3181.  
  3182.   cnum = SVAL(inbuf,smb_tid);
  3183.   fnum = GETFNUM(inbuf,smb_vwv0);
  3184.  
  3185.   CHECK_FNUM(fnum,cnum);
  3186.   CHECK_ERROR(fnum);
  3187.  
  3188.   /* Do an fstat on this file */
  3189.   if(fstat( Files[fnum].fd, &sbuf))
  3190.     return(UNIXERROR(ERRDOS,ERRnoaccess));
  3191.   
  3192.   mode = dos_mode(cnum,Files[fnum].name,&sbuf);
  3193.   
  3194.   /* Convert the times into dos times. Set create
  3195.      date to be last modify date as UNIX doesn't save
  3196.      this */
  3197.   put_dos_date2(outbuf,smb_vwv0,sbuf.st_mtime);
  3198.   put_dos_date2(outbuf,smb_vwv2,sbuf.st_atime);
  3199.   put_dos_date2(outbuf,smb_vwv4,sbuf.st_mtime);
  3200.   if (mode & aDIR)
  3201.     {
  3202.       SIVAL(outbuf,smb_vwv6,0);
  3203.       SIVAL(outbuf,smb_vwv8,0);
  3204.     }
  3205.   else
  3206.     {
  3207.       SIVAL(outbuf,smb_vwv6,sbuf.st_size);
  3208.       SIVAL(outbuf,smb_vwv8,ROUNDUP(sbuf.st_size,1024));
  3209.     }
  3210.   SSVAL(outbuf,smb_vwv10, mode);
  3211.   
  3212.   DEBUG(3,("%s reply_getattrE fnum=%d cnum=%d\n",timestring(),fnum,cnum));
  3213.   
  3214.   return(outsize);
  3215. }
  3216.  
  3217.  
  3218.  
  3219.  
  3220.  
  3221.